<template><div><p>本文档最新版为 <a href="https://learnku.com/docs/laravel/10.x" target="_blank" rel="noopener noreferrer">10.x</a>，旧版本可能放弃维护，推荐阅读最新版！</p>
<h2 id="eloquent-快速入门" tabindex="-1"><a class="header-anchor" href="#eloquent-快速入门"><span>Eloquent: 快速入门</span></a></h2>
<ul>
<li><a href="#introduction">简介</a></li>
<li><a href="#generating-model-classes">生成模型类</a></li>
<li><a href="#eloquent-model-conventions">Eloquent 模型约定</a>
<ul>
<li><a href="#table-names">表名</a></li>
<li><a href="#primary-keys">主键</a></li>
<li><a href="#uuid-and-ulid-keys">UUID 与 ULID 键</a></li>
<li><a href="#timestamps">时间戳</a></li>
<li><a href="#database-connections">数据库连接</a></li>
<li><a href="#default-attribute-values">默认属性值</a></li>
<li><a href="#configuring-eloquent-strictness">严格配置 Eloquent</a></li>
</ul>
</li>
<li><a href="#retrieving-models">模型检索</a>
<ul>
<li><a href="#collections">集合</a></li>
<li><a href="#chunking-results">分块结果集</a></li>
<li><a href="#chunking-using-lazy-collections">使用懒加载集合分块</a></li>
<li><a href="#cursors">游标</a></li>
<li><a href="#advanced-subqueries">高级子查询</a></li>
</ul>
</li>
<li><a href="#retrieving-single-models">检索单个模型 / 聚合</a>
<ul>
<li><a href="#retrieving-or-creating-models">检索或创建模型</a></li>
<li><a href="#retrieving-aggregates">检索聚合</a></li>
</ul>
</li>
<li><a href="#inserting-and-updating-models">新增 &amp; 更新模型</a>
<ul>
<li><a href="#inserts">新增</a></li>
<li><a href="#updates">更新</a></li>
<li><a href="#mass-assignment">批量任务</a></li>
<li><a href="#upserts">有则更新无则新增</a></li>
</ul>
</li>
<li><a href="#deleting-models">删除模型</a>
<ul>
<li><a href="#soft-deleting">软删除</a></li>
<li><a href="#querying-soft-deleted-models">查询已被软删除模型</a></li>
</ul>
</li>
<li><a href="#pruning-models">修剪模型</a></li>
<li><a href="#replicating-models">复制模型</a></li>
<li><a href="#query-scopes">查询作用域</a>
<ul>
<li><a href="#global-scopes">全局作用域</a></li>
<li><a href="#local-scopes">局部作用域</a></li>
</ul>
</li>
<li><a href="#comparing-models">模型对比</a></li>
<li><a href="#events">事件</a>
<ul>
<li><a href="#events-using-closures">使用闭包方法</a></li>
<li><a href="#observers">观察者</a></li>
<li><a href="#muting-events">静默事件</a></li>
</ul>
</li>
</ul>
<h2 id="简介" tabindex="-1"><a class="header-anchor" href="#简介"><span>简介</span></a></h2>
<p>Laravel 包含的 Eloquent 模块，是一个对象关系映射 (ORM)，能使你更愉快地交互数据库。当你使用 Eloquent 时，数据库中每张表都有一个相对应的” 模型” 用于操作这张表。除了能从数据表中检索数据记录之外，Eloquent 模型同时也允许你新增，更新和删除这对应表中的数据。</p>
<blockquote>
<p>[!注意]<br>
开始使用之前，请确认在你的项目里的 <code v-pre>config/database.php</code> 配置文件中已经配置好一个可用的数据库连接。关于配置数据库的更多信息，请查阅<a href="https://learnku.com/docs/laravel/11.x/database#configuration" target="_blank" rel="noopener noreferrer">数据库配置文档</a>.</p>
</blockquote>
<h4 id="laravel-bootcamp" tabindex="-1"><a class="header-anchor" href="#laravel-bootcamp"><span>Laravel Bootcamp</span></a></h4>
<p>如果你是 Laravel 新手，随时可以加入 <a href="https://bootcamp.laravel.com/" target="_blank" rel="noopener noreferrer">Laravel Bootcamp</a>。Laravel Bootcamp 将引导你使用 Eloquent 构建你的第一个 Laravel 应用程序。这是一种了解 Laravel 和 Eloquent 所提供一切的好方法。</p>
<h2 id="生成模型类" tabindex="-1"><a class="header-anchor" href="#生成模型类"><span>生成模型类</span></a></h2>
<p>首先，让我们创建一个 Eloquent 模型。模型通常位于 <code v-pre>app\Models</code> 目录并扩展 <code v-pre>Illuminate\Database\Eloquent\Model</code> 类。你可以使用 <code v-pre>make:model</code> <a href="https://learnku.com/docs/laravel/11.x/artisan" target="_blank" rel="noopener noreferrer">Artisan 命令</a>来生成一个新模型：</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh" data-title="sh"><pre v-pre class="language-bash"><code><span class="line">php artisan make:model Flight</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>如果你想在生成模型时生成一个<a href="https://learnku.com/docs/laravel/11.x/migrations" target="_blank" rel="noopener noreferrer">数据库迁移</a>，可以使用 <code v-pre>--migration</code> 或 <code v-pre>-m</code> 选项：</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh" data-title="sh"><pre v-pre class="language-bash"><code><span class="line">php artisan make:model Flight <span class="token parameter variable">--migration</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>在生成模型时，你可以生成各种其他类型的类，如工厂、填充器、策略、控制器和表单请求。此外，这些选项可以组合在一起一次创建多个类：</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh" data-title="sh"><pre v-pre class="language-bash"><code><span class="line"><span class="token comment"># 生成模型和 FlightFactory 类...</span></span>
<span class="line">php artisan make:model Flight <span class="token parameter variable">--factory</span></span>
<span class="line">php artisan make:model Flight <span class="token parameter variable">-f</span></span>
<span class="line"></span>
<span class="line"><span class="token comment"># 生成模型和 FlightSeeder 类...</span></span>
<span class="line">php artisan make:model Flight <span class="token parameter variable">--seed</span></span>
<span class="line">php artisan make:model Flight <span class="token parameter variable">-s</span></span>
<span class="line"></span>
<span class="line"><span class="token comment"># 生成模型和 FlightController 类...</span></span>
<span class="line">php artisan make:model Flight <span class="token parameter variable">--controller</span></span>
<span class="line">php artisan make:model Flight <span class="token parameter variable">-c</span></span>
<span class="line"></span>
<span class="line"><span class="token comment"># 生成模型、FlightController 资源类和表单请求类...</span></span>
<span class="line">php artisan make:model Flight <span class="token parameter variable">--controller</span> <span class="token parameter variable">--resource</span> <span class="token parameter variable">--requests</span></span>
<span class="line">php artisan make:model Flight <span class="token parameter variable">-crR</span></span>
<span class="line"></span>
<span class="line"><span class="token comment"># 生成模型和 FlightPolicy 类...</span></span>
<span class="line">php artisan make:model Flight <span class="token parameter variable">--policy</span></span>
<span class="line"></span>
<span class="line"><span class="token comment"># 生成模型和迁移、工厂、填充器和控制器...</span></span>
<span class="line">php artisan make:model Flight <span class="token parameter variable">-mfsc</span></span>
<span class="line"></span>
<span class="line"><span class="token comment"># 快捷方式生成一个模型、迁移、工厂、填充器、策略、控制器和表单请求...</span></span>
<span class="line">php artisan make:model Flight <span class="token parameter variable">--all</span></span>
<span class="line">php artisan make:model Flight <span class="token parameter variable">-a</span></span>
<span class="line"></span>
<span class="line"><span class="token comment"># 生成一个 pivot 模型...</span></span>
<span class="line">php artisan make:model Member <span class="token parameter variable">--pivot</span></span>
<span class="line">php artisan make:model Member <span class="token parameter variable">-p</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="模型检查" tabindex="-1"><a class="header-anchor" href="#模型检查"><span>模型检查</span></a></h4>
<p>有时候，仅仅通过浏览其代码很难确定模型的所有可用属性和关系。相反，尝试使用 <code v-pre>model:show</code> Artisan 命令，它能方便地概览模型的所有属性和关系：</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh" data-title="sh"><pre v-pre class="language-bash"><code><span class="line">php artisan model:show Flight</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h2 id="eloquent-模型约定" tabindex="-1"><a class="header-anchor" href="#eloquent-模型约定"><span>Eloquent 模型约定</span></a></h2>
<p><code v-pre>make:model</code> 命令生成的模型将放置在 <code v-pre>app/Models</code> 目录中。让我们检查一个基本模型类并讨论一些 Eloquent 的关键约定：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">namespace</span> <span class="token package">App<span class="token punctuation">\</span>Models</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>Model</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">Flight</span> <span class="token keyword">extends</span> <span class="token class-name">Model</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// ...</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="表名" tabindex="-1"><a class="header-anchor" href="#表名"><span>表名</span></a></h3>
<p>看完上面的示例后，你可能已经注意到，我们没有告诉 Eloquent <code v-pre>Flight</code> 模型对应的是哪个数据库表。按照惯例，类的「snake case」、复数名称将被用作表名，除非明确指定了另一个名称。因此，在本例中，Eloquent 将假设 <code v-pre>Flight</code> 模型存储记录在 <code v-pre>flights</code> 表中，而 <code v-pre>AirTrafficController</code> 模型则会存储记录在 <code v-pre>air_traffic_controllers</code> 表中。</p>
<p>如果你的模型对应的数据库表不符合此约定，你可以通过在模型上定义一个 <code v-pre>table</code> 属性来手动指定模型的表名：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">namespace</span> <span class="token package">App<span class="token punctuation">\</span>Models</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>Model</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">Flight</span> <span class="token keyword">extends</span> <span class="token class-name">Model</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * 与模型关联的表</span>
<span class="line">     *</span>
<span class="line">     * <span class="token keyword">@var</span> <span class="token class-name"><span class="token keyword">string</span></span></span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">protected</span> <span class="token variable">$table</span> <span class="token operator">=</span> <span class="token string single-quoted-string">'my_flights'</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="主键" tabindex="-1"><a class="header-anchor" href="#主键"><span>主键</span></a></h3>
<p>Eloquent 还会假设每个模型的对应数据库表都有一个名为 <code v-pre>id</code> 的主键列。如果必要，你可以在你的模型上定义一个受保护的 <code v-pre>$primaryKey</code> 属性，以指定一个不同的列作为模型的主键：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">namespace</span> <span class="token package">App<span class="token punctuation">\</span>Models</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>Model</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">Flight</span> <span class="token keyword">extends</span> <span class="token class-name">Model</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * 与表关联的主键</span>
<span class="line">     *</span>
<span class="line">     * <span class="token keyword">@var</span> <span class="token class-name"><span class="token keyword">string</span></span></span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">protected</span> <span class="token variable">$primaryKey</span> <span class="token operator">=</span> <span class="token string single-quoted-string">'flight_id'</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>此外，Eloquent 认为主键是一个递增的整数值，这意味着 Eloquent 将自动将主键转换为整数。如果你希望使用非递增或非数字主键，你必须在模型上定义一个公共的 <code v-pre>$incrementing</code> 属性，并将之设置为 <code v-pre>false</code>：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">Flight</span> <span class="token keyword">extends</span> <span class="token class-name">Model</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * 表明模型的 ID 是否自增</span>
<span class="line">     *</span>
<span class="line">     * <span class="token keyword">@var</span> <span class="token class-name"><span class="token keyword">bool</span></span></span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token variable">$incrementing</span> <span class="token operator">=</span> <span class="token constant boolean">false</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>如果模型的主键不是整数，你应该在模型上定义一个受保护的 <code v-pre>$keyType</code> 属性。此属性应该具有 <code v-pre>string</code> 的值：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">Flight</span> <span class="token keyword">extends</span> <span class="token class-name">Model</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * 主键 ID 的数据类型</span>
<span class="line">     *</span>
<span class="line">     * <span class="token keyword">@var</span> <span class="token class-name"><span class="token keyword">string</span></span></span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">protected</span> <span class="token variable">$keyType</span> <span class="token operator">=</span> <span class="token string single-quoted-string">'string'</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="「复合」主键" tabindex="-1"><a class="header-anchor" href="#「复合」主键"><span>「复合」主键</span></a></h4>
<p>Eloquent 要求每个模型至少有一个唯一标识的「ID」，可以作为其主键。Eloquent 模型不支持「复合」主键。不过，你可以在数据库表中添加额外的多列唯一索引，作为表的唯一识别主键。</p>
<h3 id="uuid-与-ulid-键" tabindex="-1"><a class="header-anchor" href="#uuid-与-ulid-键"><span>UUID 与 ULID 键</span></a></h3>
<p>你可能选择使用 UUID 而不是自增整数作为 Eloquent 模型的主键。UUID 是全球唯一的字母数字标识符，长度为 36 个字符。</p>
<p>如果你希望模型使用 UUID 键而不是自增整数键，你可以在模型上使用 <code v-pre>Illuminate\Database\Eloquent\Concerns\HasUuids</code> trait。当然，你应该确保模型有一个<a href="https://learnku.com/docs/laravel/11.x/migrations#column-method-uuid" target="_blank" rel="noopener noreferrer">相当于 UUID 的主键列</a>：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>Concerns<span class="token punctuation">\</span>HasUuids</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>Model</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">Article</span> <span class="token keyword">extends</span> <span class="token class-name">Model</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">use</span> <span class="token package">HasUuids</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token comment">// ...</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$article</span> <span class="token operator">=</span> <span class="token class-name static-context">Article</span><span class="token operator">::</span><span class="token function">create</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'title'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'Traveling to Europe'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$article</span><span class="token operator">-></span><span class="token property">id</span><span class="token punctuation">;</span> <span class="token comment">// "8f8e8478-9035-4d23-b9a7-62f4d2612ce5"</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>默认情况下，<code v-pre>HasUuids</code> trait 将为你的模型生成<a href="https://learnku.com/docs/laravel/11.x/strings#method-str-ordered-uuid" target="_blank" rel="noopener noreferrer">「有序」UUID</a>。这些 UUID 对于索引数据库存储更有效，因为它们可以按字典顺序排序。</p>
<p>你可以通过在模型上定义一个 <code v-pre>newUniqueId</code> 方法来覆盖给定模型的 UUID 生成过程。此外，你可以通过在模型上定义一个 <code v-pre>uniqueIds</code> 方法来指定哪些列应接收 UUID：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">Ramsey<span class="token punctuation">\</span>Uuid<span class="token punctuation">\</span>Uuid</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token doc-comment comment">/**</span>
<span class="line"> * 为模型生成一个新的 UUID</span>
<span class="line"> */</span></span>
<span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">newUniqueId</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">string</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token punctuation">(</span><span class="token keyword type-casting">string</span><span class="token punctuation">)</span> <span class="token class-name static-context">Uuid</span><span class="token operator">::</span><span class="token function">uuid4</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line"><span class="token doc-comment comment">/**</span>
<span class="line"> * 获取应该接收唯一标识符的列</span>
<span class="line"> *</span>
<span class="line"> * <span class="token keyword">@return</span> <span class="token class-name"><span class="token keyword">array</span></span>&lt;int, string></span>
<span class="line"> */</span></span>
<span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">uniqueIds</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">array</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token punctuation">[</span><span class="token string single-quoted-string">'id'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'discount_code'</span><span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>如果你愿意，你可以选择使用「ULID」而不是 UUID。ULID 与 UUID 类似；但是，它们只有 26 个字符长。像有序 UUID 一样，ULID 对于数据库索引来说也是按字典顺序可排序的。要使用 ULID，应该在你的模型上使用 <code v-pre>Illuminate\Database\Eloquent\Concerns\HasUlids</code> trait。你还应该确保模型具有<a href="https://learnku.com/docs/laravel/11.x/migrations#column-method-ulid" target="_blank" rel="noopener noreferrer">相当于 ULID 的主键列</a>：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>Concerns<span class="token punctuation">\</span>HasUlids</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>Model</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">Article</span> <span class="token keyword">extends</span> <span class="token class-name">Model</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">use</span> <span class="token package">HasUlids</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token comment">// ...</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$article</span> <span class="token operator">=</span> <span class="token class-name static-context">Article</span><span class="token operator">::</span><span class="token function">create</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'title'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'Traveling to Asia'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$article</span><span class="token operator">-></span><span class="token property">id</span><span class="token punctuation">;</span> <span class="token comment">// "01gd4d3tgrrfqeda94gdbtdk5c"</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="时间戳" tabindex="-1"><a class="header-anchor" href="#时间戳"><span>时间戳</span></a></h3>
<p>默认情况下，Eloquent 期望在你的模型对应的数据库表中存在 <code v-pre>created_at</code> 和 <code v-pre>updated_at</code> 列。当模型被创建或更新时，Eloquent 将自动设置这些列的值。如果你不希望这些列由 Eloquent 自动管理，你应该在模型上定义一个值为 <code v-pre>false</code> 的 <code v-pre>$timestamps</code> 属性：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">namespace</span> <span class="token package">App<span class="token punctuation">\</span>Models</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>Model</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">Flight</span> <span class="token keyword">extends</span> <span class="token class-name">Model</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * 表示模型是否应该被打上时间戳</span>
<span class="line">     *</span>
<span class="line">     * <span class="token keyword">@var</span> <span class="token class-name"><span class="token keyword">bool</span></span></span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token variable">$timestamps</span> <span class="token operator">=</span> <span class="token constant boolean">false</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>如果需要自定义模型时间戳的格式，请在模型上设置 <code v-pre>$dateFormat</code> 属性。此属性决定了日期属性在数据库中的存储格式，以及模型被序列化为数组或 JSON 时的格式：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">namespace</span> <span class="token package">App<span class="token punctuation">\</span>Models</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>Model</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">Flight</span> <span class="token keyword">extends</span> <span class="token class-name">Model</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * 模型日期列的存储格式</span>
<span class="line">     *</span>
<span class="line">     * <span class="token keyword">@var</span> <span class="token class-name"><span class="token keyword">string</span></span></span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">protected</span> <span class="token variable">$dateFormat</span> <span class="token operator">=</span> <span class="token string single-quoted-string">'U'</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>如果你需要自定义用于存储时间戳的列名，你可以在模型上定义 <code v-pre>CREATED_AT</code> 和 <code v-pre>UPDATED_AT</code> 常量：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">Flight</span> <span class="token keyword">extends</span> <span class="token class-name">Model</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">const</span> <span class="token constant">CREATED_AT</span> <span class="token operator">=</span> <span class="token string single-quoted-string">'creation_date'</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token keyword">const</span> <span class="token constant">UPDATED_AT</span> <span class="token operator">=</span> <span class="token string single-quoted-string">'updated_date'</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>如果你希望在模型进行操作时不修改其 <code v-pre>updated_at</code> 时间戳，你可以在提供给 <code v-pre>withoutTimestamps</code> 方法的闭包内对模型进行操作：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Model</span><span class="token operator">::</span><span class="token function">withoutTimestamps</span><span class="token punctuation">(</span><span class="token keyword">fn</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token variable">$post</span><span class="token operator">-></span><span class="token function">increment</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'reads'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h3 id="数据库连接" tabindex="-1"><a class="header-anchor" href="#数据库连接"><span>数据库连接</span></a></h3>
<p>默认情况下，所有 Eloquent 模型将使用为你的应用程序配置的默认数据库连接。如果你想指定与特定模型交互时应当使用的不同连接，则应该在模型上定义一个 <code v-pre>$connection</code> 属性：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">namespace</span> <span class="token package">App<span class="token punctuation">\</span>Models</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>Model</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">Flight</span> <span class="token keyword">extends</span> <span class="token class-name">Model</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * 应由模型使用的数据库连接</span>
<span class="line">     *</span>
<span class="line">     * <span class="token keyword">@var</span> <span class="token class-name"><span class="token keyword">string</span></span></span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">protected</span> <span class="token variable">$connection</span> <span class="token operator">=</span> <span class="token string single-quoted-string">'mysql'</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="默认属性值" tabindex="-1"><a class="header-anchor" href="#默认属性值"><span>默认属性值</span></a></h3>
<p>默认情况下，新实例化的模型实例不会包含任何属性值。如果你想为模型的某些属性定义默认值，你可以在模型上定义一个 <code v-pre>$attributes</code> 属性。放置在 <code v-pre>$attributes</code> 数组中的属性值应该是它们刚从数据库中读取出来时的原始「可存储」格式：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">namespace</span> <span class="token package">App<span class="token punctuation">\</span>Models</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>Model</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">Flight</span> <span class="token keyword">extends</span> <span class="token class-name">Model</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * 模型属性的默认值</span>
<span class="line">     *</span>
<span class="line">     * <span class="token keyword">@var</span> <span class="token class-name"><span class="token keyword">array</span></span></span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">protected</span> <span class="token variable">$attributes</span> <span class="token operator">=</span> <span class="token punctuation">[</span></span>
<span class="line">        <span class="token string single-quoted-string">'options'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'[]'</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token string single-quoted-string">'delayed'</span> <span class="token operator">=></span> <span class="token constant boolean">false</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="配置-eloquent-严格性" tabindex="-1"><a class="header-anchor" href="#配置-eloquent-严格性"><span>配置 Eloquent 严格性</span></a></h3>
<p>Laravel 提供了几种方法，允许你在各种情况下配置 Eloquent 的行为和「严格性」。</p>
<p>首先，<code v-pre>preventLazyLoading</code> 方法接受一个可选的布尔参数，指示是否应防止懒加载。例如，你可能希望只在非生产环境中禁用懒加载，以便你的生产环境即使在生产代码中意外出现懒加载关系也能正常运作。通常，此方法应在应用程序的 <code v-pre>AppServiceProvider</code> 的 <code v-pre>boot</code> 方法中调用：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>Model</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token doc-comment comment">/**</span>
<span class="line"> *  启动任何应用服务</span>
<span class="line"> */</span></span>
<span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">boot</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">void</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token class-name static-context">Model</span><span class="token operator">::</span><span class="token function">preventLazyLoading</span><span class="token punctuation">(</span><span class="token operator">!</span> <span class="token variable">$this</span><span class="token operator">-></span><span class="token property">app</span><span class="token operator">-></span><span class="token function">isProduction</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>此外，你还可以通过调用 <code v-pre>preventSilentlyDiscardingAttributes</code> 方法，指示 Laravel 在尝试填充无法填充的属性时抛出异常。这可以在本地开发时帮助防止意外错误，因为这时你可能尝试设置尚未添加到模型的 <code v-pre>fillable</code> 数组中的属性：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Model</span><span class="token operator">::</span><span class="token function">preventSilentlyDiscardingAttributes</span><span class="token punctuation">(</span><span class="token operator">!</span> <span class="token variable">$this</span><span class="token operator">-></span><span class="token property">app</span><span class="token operator">-></span><span class="token function">isProduction</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h2 id="检索模型" tabindex="-1"><a class="header-anchor" href="#检索模型"><span>检索模型</span></a></h2>
<p>一旦你创建了一个模型及其<a href="https://learnku.com/docs/laravel/11.x/migrationsmd#writing-migrations" target="_blank" rel="noopener noreferrer">关联的数据库表</a>，你就可以开始从你的数据库中检索数据。你可以将每个 Eloquent 模型视为一个强大的<a href="https://learnku.com/docs/laravel/11.x/queriesmd" target="_blank" rel="noopener noreferrer">查询构建器</a>，允许你流畅地查询与模型关联的数据库表。模型的 <code v-pre>all</code> 方法将检索模型关联的数据库表中的所有记录：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Models<span class="token punctuation">\</span>Flight</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">foreach</span> <span class="token punctuation">(</span><span class="token class-name static-context">Flight</span><span class="token operator">::</span><span class="token function">all</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">as</span> <span class="token variable">$flight</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">echo</span> <span class="token variable">$flight</span><span class="token operator">-></span><span class="token property">name</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="构建查询" tabindex="-1"><a class="header-anchor" href="#构建查询"><span>构建查询</span></a></h4>
<p>Eloquent 的 <code v-pre>all</code> 方法会返回模型表中的所有结果。但是，由于每个 Eloquent 模型都作为<a href="https://learnku.com/docs/laravel/11.x/queriesmd" target="_blank" rel="noopener noreferrer">查询构建器</a>，你可以对查询添加额外的约束，然后调用 <code v-pre>get</code> 方法来检索结果：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$flights</span> <span class="token operator">=</span> <span class="token class-name static-context">Flight</span><span class="token operator">::</span><span class="token function">where</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'active'</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span></span>
<span class="line">               <span class="token operator">-></span><span class="token function">orderBy</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'name'</span><span class="token punctuation">)</span></span>
<span class="line">               <span class="token operator">-></span><span class="token function">take</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">)</span></span>
<span class="line">               <span class="token operator">-></span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><blockquote>
<p><strong>注意</strong><br>
由于 Eloquent 模型是查询构建器，因此你应查看 Laravel 的所有提供的<a href="https://learnku.com/docs/laravel/11.x/queriesmd" target="_blank" rel="noopener noreferrer">查询构建器</a>方法。当编写你的 Eloquent 查询时，你可以使用这些方法中的任何一个。</p>
</blockquote>
<h4 id="刷新模型" tabindex="-1"><a class="header-anchor" href="#刷新模型"><span>刷新模型</span></a></h4>
<p>如果你已有一个从数据库检索出的 Eloquent 模型的实例，您可以使用 <code v-pre>fresh</code> 和 <code v-pre>refresh</code> 方法「刷新」模型。<code v-pre>fresh</code> 方法将从数据库重新检索模型。现有的模型实例不会受到影响：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$flight</span> <span class="token operator">=</span> <span class="token class-name static-context">Flight</span><span class="token operator">::</span><span class="token function">where</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'number'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'FR 900'</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">first</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$freshFlight</span> <span class="token operator">=</span> <span class="token variable">$flight</span><span class="token operator">-></span><span class="token function">fresh</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code v-pre>refresh</code> 方法将使用数据库中的新数据重新填充现有模型，并且还将刷新其所有加载的关系：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$flight</span> <span class="token operator">=</span> <span class="token class-name static-context">Flight</span><span class="token operator">::</span><span class="token function">where</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'number'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'FR 900'</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">first</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$flight</span><span class="token operator">-></span><span class="token property">number</span> <span class="token operator">=</span> <span class="token string single-quoted-string">'FR 456'</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$flight</span><span class="token operator">-></span><span class="token function">refresh</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$flight</span><span class="token operator">-></span><span class="token property">number</span><span class="token punctuation">;</span> <span class="token comment">// "FR 900"</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="集合" tabindex="-1"><a class="header-anchor" href="#集合"><span>集合</span></a></h3>
<p>正如我们所见，像 <code v-pre>all</code> 和 <code v-pre>get</code> 这样的 Eloquent 方法检索数据库中的多条记录。但是，这些方法并不返回普通的 PHP 数组。相反，它们返回 <code v-pre>Illuminate\Database\Eloquent\Collection</code> 的实例。</p>
<p>Eloquent 的 <code v-pre>Collection</code> 类扩展了 Laravel 的基础 <code v-pre>Illuminate\Support\Collection</code> 类，为与数据集合交互提供了<a href="https://learnku.com/docs/laravel/11.x/collectionsmd#available-methods" target="_blank" rel="noopener noreferrer">多种有用的方法</a>。例如，<code v-pre>reject</code> 方法可用于基于调用的闭包的结果移除集合中的模型：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$flights</span> <span class="token operator">=</span> <span class="token class-name static-context">Flight</span><span class="token operator">::</span><span class="token function">where</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'destination'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'Paris'</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$flights</span> <span class="token operator">=</span> <span class="token variable">$flights</span><span class="token operator">-></span><span class="token function">reject</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token class-name type-declaration">Flight</span> <span class="token variable">$flight</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token variable">$flight</span><span class="token operator">-></span><span class="token property">cancelled</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>除了 Laravel 基础集合类提供的方法外，Eloquent 集合类还提供了<a href="https://learnku.com/docs/laravel/11.x/eloquent-collectionsmd#available-methods" target="_blank" rel="noopener noreferrer">一些额外的方法</a> ，这些方法专门用于与 Eloquent 模型的集合交互。</p>
<p>由于所有的 Laravel 集合都实现了 PHP 的可迭代接口，你可以像循环数组一样循环集合：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">foreach</span> <span class="token punctuation">(</span><span class="token variable">$flights</span> <span class="token keyword">as</span> <span class="token variable">$flight</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">echo</span> <span class="token variable">$flight</span><span class="token operator">-></span><span class="token property">name</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="分块结果" tabindex="-1"><a class="header-anchor" href="#分块结果"><span>分块结果</span></a></h3>
<p>如果你尝试通过 <code v-pre>all</code> 或 <code v-pre>get</code> 方法加载数万条 Eloquent 记录，你的应用程序可能会耗尽内存。为了避免出现这种情况， <code v-pre>chunk</code> 方法可以用来更有效地处理这些大量数据。</p>
<p><code v-pre>chunk</code> 方法将传递 Eloquent 模型的子集，将它们交给闭包进行处理。由于一次只检索当前的 Eloquent 模型块的数据，所以当处理大量模型数据时， <code v-pre>chunk</code> 方法将显着减少内存使用：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Models<span class="token punctuation">\</span>Flight</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>Collection</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token class-name static-context">Flight</span><span class="token operator">::</span><span class="token function">chunk</span><span class="token punctuation">(</span><span class="token number">200</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token class-name type-declaration">Collection</span> <span class="token variable">$flights</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">foreach</span> <span class="token punctuation">(</span><span class="token variable">$flights</span> <span class="token keyword">as</span> <span class="token variable">$flight</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">        <span class="token comment">// ...</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>传递给 <code v-pre>chunk</code> 方法的第一个参数是你希望每个「块」接收的记录数量。作为第二个参数传递的闭包将被调用，并检索从数据库中检索的每个块。将执行数据库查询来检索传递给闭包的每个记录块。</p>
<p>如果要根据在迭代结果时也将更新的列来筛选 <code v-pre>chunk</code> 方法的结果，则应使用 <code v-pre>chunkById</code> 方法。在这种场景下如果使用 <code v-pre>chunk</code>  方法的话，得到的结果可能和预想中的不一样。在内部，<code v-pre>chunkById</code> 方法总是会检索到 <code v-pre>id</code> 列大于前一个块中最后一个模型的模型：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Flight</span><span class="token operator">::</span><span class="token function">where</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'departed'</span><span class="token punctuation">,</span> <span class="token constant boolean">true</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token operator">-></span><span class="token function">chunkById</span><span class="token punctuation">(</span><span class="token number">200</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token class-name type-declaration">Collection</span> <span class="token variable">$flights</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">        <span class="token variable">$flights</span><span class="token operator">-></span><span class="token property">each</span><span class="token operator">-></span><span class="token function">update</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'departed'</span> <span class="token operator">=></span> <span class="token constant boolean">false</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token variable">$column</span> <span class="token operator">=</span> <span class="token string single-quoted-string">'id'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="使用惰性集合分块" tabindex="-1"><a class="header-anchor" href="#使用惰性集合分块"><span>使用惰性集合分块</span></a></h3>
<p><code v-pre>lazy</code> 方法在工作方式上类似于 <a href="#chunking-results"><code v-pre>chunk</code> 方法</a>，在幕后，它通过分块执行查询。但是，lazy 方法不是将每个块直接传递到回调中，而是返回 Eloquent 模型的扁平化 <a href="https://learnku.com/docs/laravel/11.x/collectionsmd#lazy-collections" target="_blank" rel="noopener noreferrer"><code v-pre>LazyCollection</code></a> ，让你可以将结果作为单一流进行交互：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Models<span class="token punctuation">\</span>Flight</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">foreach</span> <span class="token punctuation">(</span><span class="token class-name static-context">Flight</span><span class="token operator">::</span><span class="token function">lazy</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">as</span> <span class="token variable">$flight</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// ...</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>如果你是根据你也将在迭代结果时更新的列来过滤 <code v-pre>lazy</code> 方法的结果，你应该使用 <code v-pre>lazyById</code> 方法。在内部，<code v-pre>lazyById</code> 方法将始终检索 <code v-pre>id</code> 列大于前一个块中最后一个模型的模型：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Flight</span><span class="token operator">::</span><span class="token function">where</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'departed'</span><span class="token punctuation">,</span> <span class="token constant boolean">true</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token operator">-></span><span class="token function">lazyById</span><span class="token punctuation">(</span><span class="token number">200</span><span class="token punctuation">,</span> <span class="token variable">$column</span> <span class="token operator">=</span> <span class="token string single-quoted-string">'id'</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token operator">-></span><span class="token property">each</span><span class="token operator">-></span><span class="token function">update</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'departed'</span> <span class="token operator">=></span> <span class="token constant boolean">false</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>你可以使用 <code v-pre>lazyByIdDesc</code> 方法根据 <code v-pre>id</code> 的降序来过滤结果。</p>
<h3 id="游标" tabindex="-1"><a class="header-anchor" href="#游标"><span>游标</span></a></h3>
<p>与 <code v-pre>lazy</code> 方法类似，<code v-pre>cursor</code> 方法可用于在迭代数以万计的 Eloquent 模型记录时显著降低应用程序的内存消耗。</p>
<p><code v-pre>cursor</code> 方法将只执行一次数据库查询；然而，各个 Eloquent 模型将在实际迭代时才被填充实例化。因此，在迭代游标时，一次只保持一个 Eloquent 模型在内存中。</p>
<blockquote>
<p><strong>注意</strong><br>
由于 cursor 方法一次只能在内存中保存一个 Eloquent 模型，因此它不能预加载关系。如果需要预加载关系，请考虑使用 <a href="#chunking-using-lazy-collections">lazy 方法</a>。</p>
</blockquote>
<p>在内部，<code v-pre>cursor</code> 方法使用 PHP <a href="https://www.php.net/manual/en/language.generators.overview.php" target="_blank" rel="noopener noreferrer">生成器</a>来实现该功能：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Models<span class="token punctuation">\</span>Flight</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">foreach</span> <span class="token punctuation">(</span><span class="token class-name static-context">Flight</span><span class="token operator">::</span><span class="token function">where</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'destination'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'Zurich'</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">cursor</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">as</span> <span class="token variable">$flight</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// ...</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code v-pre>cursor</code> 方法返回一个 <code v-pre>Illuminate\Support\LazyCollection</code> 实例。<a href="https://learnku.com/docs/laravel/11.x/collectionsmd#lazy-collections" target="_blank" rel="noopener noreferrer">惰性集合</a> 允许你在一次只加载单个模型到内存的同时，使用在典型 Laravel 集合上可用的许多集合方法：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Models<span class="token punctuation">\</span>User</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$users</span> <span class="token operator">=</span> <span class="token class-name static-context">User</span><span class="token operator">::</span><span class="token function">cursor</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">filter</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token class-name type-declaration">User</span> <span class="token variable">$user</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token variable">$user</span><span class="token operator">-></span><span class="token property">id</span> <span class="token operator">></span> <span class="token number">500</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">foreach</span> <span class="token punctuation">(</span><span class="token variable">$users</span> <span class="token keyword">as</span> <span class="token variable">$user</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">echo</span> <span class="token variable">$user</span><span class="token operator">-></span><span class="token property">id</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>尽管 <code v-pre>cursor</code> 方法的内存使用量远低于常规查询（因为每次只保留一个 Eloquent 模型在内存中），但最终仍会耗尽内存。这是<a href="https://www.php.net/manual/en/mysqlinfo.concepts.buffering.php" target="_blank" rel="noopener noreferrer">由于 PHP 的 PDO 驱动在其缓冲区内部缓存所有原始查询结果</a>。如果你处理的是非常大量的 Eloquent 记录，请考虑使用 <a href="#chunking-using-lazy-collections"><code v-pre>lazy</code> 方法</a>。</p>
<h3 id="高级子查询" tabindex="-1"><a class="header-anchor" href="#高级子查询"><span>高级子查询</span></a></h3>
<h4 id="selects-子查询" tabindex="-1"><a class="header-anchor" href="#selects-子查询"><span>selects 子查询</span></a></h4>
<p>Eloquent 还提供高级子查询支持，允许你在单个查询中从相关表中提取信息。例如，假设我们有一个飞行 <code v-pre>destinations</code> 的表和一个到达目的地的 <code v-pre>flights</code> 表。<code v-pre>flights</code> 表包含一个 <code v-pre>arrived_at</code> 列，指示飞机到达目的地的时间。</p>
<p>使用查询构造器可用的子查询功能 <code v-pre>select</code> 和 <code v-pre>addSelect</code> 方法，我们可以使用单个语句查询所有 <code v-pre>destinations</code> 以及最近到达该目的地的航班的名称，：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Models<span class="token punctuation">\</span>Destination</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Models<span class="token punctuation">\</span>Flight</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">return</span> <span class="token class-name static-context">Destination</span><span class="token operator">::</span><span class="token function">addSelect</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'last_flight'</span> <span class="token operator">=></span> <span class="token class-name static-context">Flight</span><span class="token operator">::</span><span class="token function">select</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'name'</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token operator">-></span><span class="token function">whereColumn</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'destination_id'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'destinations.id'</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token operator">-></span><span class="token function">orderByDesc</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'arrived_at'</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token operator">-></span><span class="token function">limit</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="子查询排序" tabindex="-1"><a class="header-anchor" href="#子查询排序"><span>子查询排序</span></a></h4>
<p>此外，查询构造器的 <code v-pre>orderBy</code> 函数支持子查询。继续使用我们的飞行示例，我们可以使用此功能对所有目的地进行排序，基于最后一次航班到达目的地的时间。这可以在执行单个数据库查询的同时完成：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">return</span> <span class="token class-name static-context">Destination</span><span class="token operator">::</span><span class="token function">orderByDesc</span><span class="token punctuation">(</span></span>
<span class="line">    <span class="token class-name static-context">Flight</span><span class="token operator">::</span><span class="token function">select</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'arrived_at'</span><span class="token punctuation">)</span></span>
<span class="line">        <span class="token operator">-></span><span class="token function">whereColumn</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'destination_id'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'destinations.id'</span><span class="token punctuation">)</span></span>
<span class="line">        <span class="token operator">-></span><span class="token function">orderByDesc</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'arrived_at'</span><span class="token punctuation">)</span></span>
<span class="line">        <span class="token operator">-></span><span class="token function">limit</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="检索单个模型-聚合" tabindex="-1"><a class="header-anchor" href="#检索单个模型-聚合"><span>检索单个模型 / 聚合</span></a></h2>
<p>除了根据给定查询检索所有匹配的记录之外，你还可以使用 <code v-pre>find</code>、<code v-pre>first</code> 或 <code v-pre>firstWhere</code> 方法检索单个记录。这些方法不是返回模型集合，而是返回单个模型实例：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Models<span class="token punctuation">\</span>Flight</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token comment">// 根据主键检索模型...</span></span>
<span class="line"><span class="token variable">$flight</span> <span class="token operator">=</span> <span class="token class-name static-context">Flight</span><span class="token operator">::</span><span class="token function">find</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token comment">// 检索与查询条件匹配的第一个模型...</span></span>
<span class="line"><span class="token variable">$flight</span> <span class="token operator">=</span> <span class="token class-name static-context">Flight</span><span class="token operator">::</span><span class="token function">where</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'active'</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">first</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token comment">// 替代检索与查询条件匹配的第一个模型...</span></span>
<span class="line"><span class="token variable">$flight</span> <span class="token operator">=</span> <span class="token class-name static-context">Flight</span><span class="token operator">::</span><span class="token function">firstWhere</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'active'</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>有时候你可能希望在没有找到结果时执行一些其他动作。<code v-pre>findOr</code> 和 <code v-pre>firstOr</code> 方法将返回单个模型实例，或者如果没有找到结果，执行给定的闭包。闭包返回的值将被视为方法的结果</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$flight</span> <span class="token operator">=</span> <span class="token class-name static-context">Flight</span><span class="token operator">::</span><span class="token function">findOr</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// ...</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$flight</span> <span class="token operator">=</span> <span class="token class-name static-context">Flight</span><span class="token operator">::</span><span class="token function">where</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'legs'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'>'</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">firstOr</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// ...</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="未找到时抛出异常" tabindex="-1"><a class="header-anchor" href="#未找到时抛出异常"><span>未找到时抛出异常</span></a></h4>
<p>有时候你可能希望在找不到模型时抛出异常。这在路由或控制器中特别有用。<code v-pre>findOrFail</code> 和 <code v-pre>firstOrFail</code> 方法将检索查询的第一个结果；但是，如果没有找到结果，将抛出 <code v-pre>Illuminate\Database\Eloquent\ModelNotFoundException</code> 异常：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$flight</span> <span class="token operator">=</span> <span class="token class-name static-context">Flight</span><span class="token operator">::</span><span class="token function">findOrFail</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$flight</span> <span class="token operator">=</span> <span class="token class-name static-context">Flight</span><span class="token operator">::</span><span class="token function">where</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'legs'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'>'</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">firstOrFail</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>如果未捕获 <code v-pre>ModelNotFoundException</code>，将自动向客户端发送 404 HTTP 响应：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Models<span class="token punctuation">\</span>Flight</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token class-name static-context">Route</span><span class="token operator">::</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'/api/flights/{id}'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token keyword type-hint">string</span> <span class="token variable">$id</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token class-name static-context">Flight</span><span class="token operator">::</span><span class="token function">findOrFail</span><span class="token punctuation">(</span><span class="token variable">$id</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="检索或创建模型" tabindex="-1"><a class="header-anchor" href="#检索或创建模型"><span>检索或创建模型</span></a></h3>
<p><code v-pre>firstOrCreate</code> 方法将尝试使用给定的列/值对定位数据库记录。如果在数据库中找不到模型，则将插入合并第一个数组参数与可选的第二个数组参数的属性的记录：</p>
<p>与 <code v-pre>firstOrCreate</code> 方法类似，<code v-pre>firstOrNew</code> 方法将尝试定位与给定属性匹配的数据库记录。但是，如果没有找到模型，则会返回一个新的模型实例。请注意，<code v-pre>firstOrNew</code> 返回的模型尚未持久化到数据库。你需要手动调用 <code v-pre>save</code> 方法来持久化它：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Models<span class="token punctuation">\</span>Flight</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token comment">// 按名称检索航班，如果不存在则创建它...</span></span>
<span class="line"><span class="token variable">$flight</span> <span class="token operator">=</span> <span class="token class-name static-context">Flight</span><span class="token operator">::</span><span class="token function">firstOrCreate</span><span class="token punctuation">(</span><span class="token punctuation">[</span></span>
<span class="line">    <span class="token string single-quoted-string">'name'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'London to Paris'</span></span>
<span class="line"><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token comment">// 按名称检索航班或使用名称、延迟和到达时间属性创建它...</span></span>
<span class="line"><span class="token variable">$flight</span> <span class="token operator">=</span> <span class="token class-name static-context">Flight</span><span class="token operator">::</span><span class="token function">firstOrCreate</span><span class="token punctuation">(</span></span>
<span class="line">    <span class="token punctuation">[</span><span class="token string single-quoted-string">'name'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'London to Paris'</span><span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token punctuation">[</span><span class="token string single-quoted-string">'delayed'</span> <span class="token operator">=></span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'arrival_time'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'11:30'</span><span class="token punctuation">]</span></span>
<span class="line"><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token comment">// 按名称检索航班或实例化一个新的航班实例...</span></span>
<span class="line"><span class="token variable">$flight</span> <span class="token operator">=</span> <span class="token class-name static-context">Flight</span><span class="token operator">::</span><span class="token function">firstOrNew</span><span class="token punctuation">(</span><span class="token punctuation">[</span></span>
<span class="line">    <span class="token string single-quoted-string">'name'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'London to Paris'</span></span>
<span class="line"><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token comment">// 按名称检索航班或使用名称、延迟和到达时间属性实例化...</span></span>
<span class="line"><span class="token variable">$flight</span> <span class="token operator">=</span> <span class="token class-name static-context">Flight</span><span class="token operator">::</span><span class="token function">firstOrNew</span><span class="token punctuation">(</span></span>
<span class="line">    <span class="token punctuation">[</span><span class="token string single-quoted-string">'name'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'Tokyo to Sydney'</span><span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token punctuation">[</span><span class="token string single-quoted-string">'delayed'</span> <span class="token operator">=></span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'arrival_time'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'11:30'</span><span class="token punctuation">]</span></span>
<span class="line"><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="检索聚合" tabindex="-1"><a class="header-anchor" href="#检索聚合"><span>检索聚合</span></a></h3>
<p>在与 Eloquent 模型交互时，你还可以使用 <code v-pre>count</code>、<code v-pre>sum</code>、<code v-pre>max</code> 和 Laravel <a href="https://learnku.com/docs/laravel/11.x/queriesmd" target="_blank" rel="noopener noreferrer">查询构建器</a>提供的其他 <a href="https://learnku.com/docs/laravel/11.x/queriesmd#aggregates" target="_blank" rel="noopener noreferrer">聚合方法</a> 。正如你所期望的，这些方法返回一个数字值而不是 Eloquent 模型实例：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$count</span> <span class="token operator">=</span> <span class="token class-name static-context">Flight</span><span class="token operator">::</span><span class="token function">where</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'active'</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">count</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$max</span> <span class="token operator">=</span> <span class="token class-name static-context">Flight</span><span class="token operator">::</span><span class="token function">where</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'active'</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">max</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'price'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="插入和更新模型" tabindex="-1"><a class="header-anchor" href="#插入和更新模型"><span>插入和更新模型</span></a></h2>
<h3 id="插入" tabindex="-1"><a class="header-anchor" href="#插入"><span>插入</span></a></h3>
<p>当然，使用 Eloquent 时，我们不仅需要从数据库中检索模型。我们还需要插入新的记录。幸运的是，Eloquent 使其变得简单。要将新记录插入到数据库中，你应该实例化一个新的模型实例并设置模型的属性。然后，在模型实例上调用 <code v-pre>save</code> 方法：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">namespace</span> <span class="token package">App<span class="token punctuation">\</span>Http<span class="token punctuation">\</span>Controllers</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Http<span class="token punctuation">\</span>Controllers<span class="token punctuation">\</span>Controller</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Models<span class="token punctuation">\</span>Flight</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Http<span class="token punctuation">\</span>RedirectResponse</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Http<span class="token punctuation">\</span>Request</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">FlightController</span> <span class="token keyword">extends</span> <span class="token class-name">Controller</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     *  在数据库中存储新航班</span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">store</span><span class="token punctuation">(</span><span class="token class-name type-declaration">Request</span> <span class="token variable">$request</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token class-name return-type">RedirectResponse</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token comment">// 验证请求...</span></span>
<span class="line"></span>
<span class="line">        <span class="token variable">$flight</span> <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Flight</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">        <span class="token variable">$flight</span><span class="token operator">-></span><span class="token property">name</span> <span class="token operator">=</span> <span class="token variable">$request</span><span class="token operator">-></span><span class="token property">name</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">        <span class="token variable">$flight</span><span class="token operator">-></span><span class="token function">save</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">        <span class="token keyword">return</span> <span class="token function">redirect</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'/flights'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>在此示例中，我们将传入的 HTTP 请求的 <code v-pre>name</code> 字段分配给 <code v-pre>App\Models\Flight</code> 模型实例的 <code v-pre>name</code> 属性。当我们调用 <code v-pre>save</code> 方法时，将在数据库中插入一条记录。在调用 <code v-pre>save</code> 方法时，模型的 <code v-pre>created_at</code> 和 <code v-pre>updated_at</code> 时间戳将自动设置，因此无需手动设置它们。</p>
<p>或者，你可以使用 <code v-pre>create</code> 方法通过单个 PHP 语句「保存」新模型。<code v-pre>create</code> 方法将返回插入的模型实例：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Models<span class="token punctuation">\</span>Flight</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$flight</span> <span class="token operator">=</span> <span class="token class-name static-context">Flight</span><span class="token operator">::</span><span class="token function">create</span><span class="token punctuation">(</span><span class="token punctuation">[</span></span>
<span class="line">    <span class="token string single-quoted-string">'name'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'London to Paris'</span><span class="token punctuation">,</span></span>
<span class="line"><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>但是，在使用 <code v-pre>create</code> 方法之前，你需要在模型类上指定 <code v-pre>fillable</code> 或 <code v-pre>guarded</code> 属性。这些属性是必需的，因为所有 Eloquent 模型默认受到批量赋值漏洞的保护。要了解有关批量赋值的更多信息，请参阅 <a href="#mass-assignment">批量赋值文档</a>。</p>
<h3 id="更新" tabindex="-1"><a class="header-anchor" href="#更新"><span>更新</span></a></h3>
<p><code v-pre>save</code> 方法也可用来更新已存在于数据库中的模型。要更新模型，你应该检索它并设置你希望更新的任何属性。然后，应该调用模型的 <code v-pre>save</code> 方法。同样，<code v-pre>updated_at</code> 时间戳将自动更新，因此无需手动设置其值：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Models<span class="token punctuation">\</span>Flight</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$flight</span> <span class="token operator">=</span> <span class="token class-name static-context">Flight</span><span class="token operator">::</span><span class="token function">find</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$flight</span><span class="token operator">-></span><span class="token property">name</span> <span class="token operator">=</span> <span class="token string single-quoted-string">'Paris to London'</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$flight</span><span class="token operator">-></span><span class="token function">save</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>有时，你可能需要更新现有模型或在没有匹配模型存在时创建新模型。与 <code v-pre>firstOrCreate</code> 方法类似，<code v-pre>updateOrCreate</code> 方法持久化模型，因此不需要手动调用 <code v-pre>save</code> 方法。</p>
<p>在下面的示例中，如果存在一个从 <code v-pre>Oakland</code> 出发到 <code v-pre>San Diego</code> 目的地的航班，它的 <code v-pre>price</code> 和 <code v-pre>discounted</code> 列将被更新。如果没有这样的航班存在，则将创建一个具有合并第一个参数数组与第二个参数数组的属性的新航班：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$flight</span> <span class="token operator">=</span> <span class="token class-name static-context">Flight</span><span class="token operator">::</span><span class="token function">updateOrCreate</span><span class="token punctuation">(</span></span>
<span class="line">    <span class="token punctuation">[</span><span class="token string single-quoted-string">'departure'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'Oakland'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'destination'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'San Diego'</span><span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token punctuation">[</span><span class="token string single-quoted-string">'price'</span> <span class="token operator">=></span> <span class="token number">99</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'discounted'</span> <span class="token operator">=></span> <span class="token number">1</span><span class="token punctuation">]</span></span>
<span class="line"><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="批量更新" tabindex="-1"><a class="header-anchor" href="#批量更新"><span>批量更新</span></a></h4>
<p>你也可以对匹配给定查询的模型进行更新。在这个例子中，所有被标记为活跃（<code v-pre>active</code>）且目的地为 <code v-pre>San Diego</code> 的航班将被标记为延误：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Flight</span><span class="token operator">::</span><span class="token function">where</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'active'</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span></span>
<span class="line">      <span class="token operator">-></span><span class="token function">where</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'destination'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'San Diego'</span><span class="token punctuation">)</span></span>
<span class="line">      <span class="token operator">-></span><span class="token function">update</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'delayed'</span> <span class="token operator">=></span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code v-pre>update</code> 方法期望一个由列名和值对组成的数组，表示应该更新的列。<code v-pre>update</code> 方法返回受影响的行数。</p>
<blockquote>
<p><strong>注意</strong><br>
通过 Eloquent 进行批量更新时，<code v-pre>saving</code>, <code v-pre>saved</code>, <code v-pre>updating</code> 和 <code v-pre>updated</code> 模型事件不会被模型触发。这是因为执行批量更新时，模型实际上从未被检索过。</p>
</blockquote>
<h4 id="检查属性变化" tabindex="-1"><a class="header-anchor" href="#检查属性变化"><span>检查属性变化</span></a></h4>
<p>Eloquent 提供了 <code v-pre>isDirty</code>、<code v-pre>isClean</code> 和 <code v-pre>wasChanged</code> 方法来检查模型的内部状态，并确定自模型最初检索以来其属性的变化。</p>
<p><code v-pre>isDirty</code> 方法确定自从模型被检索以来，模型的任何属性是否发生了变化。你可以传递一个具体的属性名称或一组属性到 <code v-pre>isDirty</code> 方法，以确定任何属性是否「脏」。<code v-pre>isClean</code> 方法将确定自模型被检索以来，一个属性是否保持不变。这个方法也接受一个可选的属性参数：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Models<span class="token punctuation">\</span>User</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$user</span> <span class="token operator">=</span> <span class="token class-name static-context">User</span><span class="token operator">::</span><span class="token function">create</span><span class="token punctuation">(</span><span class="token punctuation">[</span></span>
<span class="line">    <span class="token string single-quoted-string">'first_name'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'Taylor'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token string single-quoted-string">'last_name'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'Otwell'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token string single-quoted-string">'title'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'Developer'</span><span class="token punctuation">,</span></span>
<span class="line"><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$user</span><span class="token operator">-></span><span class="token property">title</span> <span class="token operator">=</span> <span class="token string single-quoted-string">'Painter'</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$user</span><span class="token operator">-></span><span class="token function">isDirty</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// true</span></span>
<span class="line"><span class="token variable">$user</span><span class="token operator">-></span><span class="token function">isDirty</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'title'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// true</span></span>
<span class="line"><span class="token variable">$user</span><span class="token operator">-></span><span class="token function">isDirty</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'first_name'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// false</span></span>
<span class="line"><span class="token variable">$user</span><span class="token operator">-></span><span class="token function">isDirty</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'first_name'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'title'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// true</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$user</span><span class="token operator">-></span><span class="token function">isClean</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// false</span></span>
<span class="line"><span class="token variable">$user</span><span class="token operator">-></span><span class="token function">isClean</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'title'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// false</span></span>
<span class="line"><span class="token variable">$user</span><span class="token operator">-></span><span class="token function">isClean</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'first_name'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// true</span></span>
<span class="line"><span class="token variable">$user</span><span class="token operator">-></span><span class="token function">isClean</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'first_name'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'title'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// false</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$user</span><span class="token operator">-></span><span class="token function">save</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$user</span><span class="token operator">-></span><span class="token function">isDirty</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// false</span></span>
<span class="line"><span class="token variable">$user</span><span class="token operator">-></span><span class="token function">isClean</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// true</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code v-pre>wasChanged</code> 方法确定当模型在当前请求周期内最后一次保存时，其属性是否被更改。如果需要，你可以传递一个属性名来查看特定属性是否有变化：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$user</span> <span class="token operator">=</span> <span class="token class-name static-context">User</span><span class="token operator">::</span><span class="token function">create</span><span class="token punctuation">(</span><span class="token punctuation">[</span></span>
<span class="line">    <span class="token string single-quoted-string">'first_name'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'Taylor'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token string single-quoted-string">'last_name'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'Otwell'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token string single-quoted-string">'title'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'Developer'</span><span class="token punctuation">,</span></span>
<span class="line"><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$user</span><span class="token operator">-></span><span class="token property">title</span> <span class="token operator">=</span> <span class="token string single-quoted-string">'Painter'</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$user</span><span class="token operator">-></span><span class="token function">save</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$user</span><span class="token operator">-></span><span class="token function">wasChanged</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// true</span></span>
<span class="line"><span class="token variable">$user</span><span class="token operator">-></span><span class="token function">wasChanged</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'title'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// true</span></span>
<span class="line"><span class="token variable">$user</span><span class="token operator">-></span><span class="token function">wasChanged</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'title'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'slug'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// true</span></span>
<span class="line"><span class="token variable">$user</span><span class="token operator">-></span><span class="token function">wasChanged</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'first_name'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// false</span></span>
<span class="line"><span class="token variable">$user</span><span class="token operator">-></span><span class="token function">wasChanged</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'first_name'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'title'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// true</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code v-pre>getOriginal</code> 方法返回一个数组，包含模型原始属性，不管从检索起模型是否发生了任何变化。如果需要，你可以传递一个特定的属性名来获取特定属性的原始值：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$user</span> <span class="token operator">=</span> <span class="token class-name static-context">User</span><span class="token operator">::</span><span class="token function">find</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$user</span><span class="token operator">-></span><span class="token property">name</span><span class="token punctuation">;</span> <span class="token comment">// John</span></span>
<span class="line"><span class="token variable">$user</span><span class="token operator">-></span><span class="token property">email</span><span class="token punctuation">;</span> <span class="token comment">// john@example.com</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$user</span><span class="token operator">-></span><span class="token property">name</span> <span class="token operator">=</span> <span class="token string double-quoted-string">"Jack"</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token variable">$user</span><span class="token operator">-></span><span class="token property">name</span><span class="token punctuation">;</span> <span class="token comment">// Jack</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$user</span><span class="token operator">-></span><span class="token function">getOriginal</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'name'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// John</span></span>
<span class="line"><span class="token variable">$user</span><span class="token operator">-></span><span class="token function">getOriginal</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 原始属性的数组...</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="批量赋值" tabindex="-1"><a class="header-anchor" href="#批量赋值"><span>批量赋值</span></a></h3>
<p>你可以使用 <code v-pre>create</code> 方法通过一个 PHP 语句来「保存」一个新模型。插入的模型实例将由该方法返回给你：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Models<span class="token punctuation">\</span>Flight</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$flight</span> <span class="token operator">=</span> <span class="token class-name static-context">Flight</span><span class="token operator">::</span><span class="token function">create</span><span class="token punctuation">(</span><span class="token punctuation">[</span></span>
<span class="line">    <span class="token string single-quoted-string">'name'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'London to Paris'</span><span class="token punctuation">,</span></span>
<span class="line"><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>然而，在使用 <code v-pre>create</code> 方法之前，你需要在模型类上指定一个 <code v-pre>fillable</code> 或 <code v-pre>guarded</code> 属性。这些属性是必需的，因为所有 Eloquent 模型默认都被保护免受批量赋值漏洞的影响。</p>
<p>批量赋值漏洞发生在用户通过 HTTP 请求传递一个非预期字段，而该字段则改变了你数据库中未预期的列。例如，恶意用户可能通过 HTTP 请求发送一个 <code v-pre>is_admin</code> 参数，然后被传递给模型的 <code v-pre>create</code> 方法，允许用户将自己升级为管理员。</p>
<p>因此，要开始使用，你应该定义哪些模型属性想要使其可批量赋值。你可以使用模型上的 <code v-pre>$fillable</code> 属性来实现这一点。例如，让我们使 <code v-pre>Flight</code> 模型的 <code v-pre>name</code> 属性可批量赋值：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">namespace</span> <span class="token package">App<span class="token punctuation">\</span>Models</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>Model</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">Flight</span> <span class="token keyword">extends</span> <span class="token class-name">Model</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * 可批量赋值的属性</span>
<span class="line">     *</span>
<span class="line">     * <span class="token keyword">@var</span> <span class="token class-name"><span class="token keyword">array</span></span></span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">protected</span> <span class="token variable">$fillable</span> <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token string single-quoted-string">'name'</span><span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>一旦指定了哪些属性可批量赋值，你可以使用 <code v-pre>create</code> 方法来在数据库中插入新记录。<code v-pre>create</code> 方法返回新创建的模型实例：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$flight</span> <span class="token operator">=</span> <span class="token class-name static-context">Flight</span><span class="token operator">::</span><span class="token function">create</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'name'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'London to Paris'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>如果你已有一个模型实例，你可以使用 <code v-pre>fill</code> 方法来用一个属性数组填充它：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$flight</span><span class="token operator">-></span><span class="token function">fill</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'name'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'Amsterdam to Frankfurt'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h4 id="批量赋值-json-列" tabindex="-1"><a class="header-anchor" href="#批量赋值-json-列"><span>批量赋值 &amp; JSON 列</span></a></h4>
<p>在赋值 JSON 列时，每个列的可批量赋值键必须在模型的 <code v-pre>$fillable</code> 数组中指定。出于安全性考虑，当使用 <code v-pre>guarded</code> 属性时，Laravel 不支持更新嵌套的 JSON 属性：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token doc-comment comment">/**</span>
<span class="line"> * 可批量赋值的属性</span>
<span class="line"> *</span>
<span class="line"> * <span class="token keyword">@var</span> <span class="token class-name"><span class="token keyword">array</span></span></span>
<span class="line"> */</span></span>
<span class="line"><span class="token keyword">protected</span> <span class="token variable">$fillable</span> <span class="token operator">=</span> <span class="token punctuation">[</span></span>
<span class="line">    <span class="token string single-quoted-string">'options->enabled'</span><span class="token punctuation">,</span></span>
<span class="line"><span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="允许批量赋值" tabindex="-1"><a class="header-anchor" href="#允许批量赋值"><span>允许批量赋值</span></a></h4>
<p>如果你希望使所有的属性都可以被批量赋值，你可以将模型的 <code v-pre>$guarded</code> 属性定义为一个空数组。如果你选择不保护你的模型，你应特别小心，始终手工制作传递给 Eloquent 的 <code v-pre>fill</code>、<code v-pre>create</code> 和 <code v-pre>update</code> 方法的数组：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token doc-comment comment">/**</span>
<span class="line"> * 不是批量赋值的属性</span>
<span class="line"> *</span>
<span class="line"> * <span class="token keyword">@var</span> <span class="token class-name"><span class="token keyword">array</span></span></span>
<span class="line"> */</span></span>
<span class="line"><span class="token keyword">protected</span> <span class="token variable">$guarded</span> <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="批量赋值异常" tabindex="-1"><a class="header-anchor" href="#批量赋值异常"><span>批量赋值异常</span></a></h4>
<p>默认情况下，在进行批量赋值操作时，不在 <code v-pre>$fillable</code> 数组中的属性会被默默地丢弃。在生产环境中，这是预期的行为；然而，在本地开发过程中，模型更改不生效可能导致混淆。</p>
<p>如果你愿意，你可以指示 Laravel 在尝试填充一个不可填充的属性时抛出异常，通过调用 <code v-pre>preventSilentlyDiscardingAttributes</code> 方法。通常，这个方法应该在你应用程序的 <code v-pre>AppServiceProvider</code> 类的 <code v-pre>boot</code> 方法中调用：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>Model</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token doc-comment comment">/**</span>
<span class="line"> * 启动任何应用程序服务</span>
<span class="line"> */</span></span>
<span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">boot</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">void</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token class-name static-context">Model</span><span class="token operator">::</span><span class="token function">preventSilentlyDiscardingAttributes</span><span class="token punctuation">(</span><span class="token variable">$this</span><span class="token operator">-></span><span class="token property">app</span><span class="token operator">-></span><span class="token function">isLocal</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="upserts" tabindex="-1"><a class="header-anchor" href="#upserts"><span>Upserts</span></a></h3>
<p>Eloquent 的 <code v-pre>upsert</code> 方法可用于在单个原子操作中更新或创建记录。该方法的第一个参数包含要插入或更新的值，第二个参数列出在关联表中唯一标识记录的列。该方法的第三个也是最后一个参数是一个数组，它包含如果数据库中已存在匹配的记录时应更新的列。如果在模型上启用了时间戳，<code v-pre>upsert</code> 方法会自动设置 <code v-pre>created_at</code> 和 <code v-pre>updated_at</code> 时间戳：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Flight</span><span class="token operator">::</span><span class="token function">upsert</span><span class="token punctuation">(</span><span class="token punctuation">[</span></span>
<span class="line">    <span class="token punctuation">[</span><span class="token string single-quoted-string">'departure'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'Oakland'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'destination'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'San Diego'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'price'</span> <span class="token operator">=></span> <span class="token number">99</span><span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token punctuation">[</span><span class="token string single-quoted-string">'departure'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'Chicago'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'destination'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'New York'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'price'</span> <span class="token operator">=></span> <span class="token number">150</span><span class="token punctuation">]</span></span>
<span class="line"><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token argument-name">uniqueBy</span><span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token string single-quoted-string">'departure'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'destination'</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token argument-name">update</span><span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token string single-quoted-string">'price'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><blockquote>
<p><strong>注意</strong><br>
除了 SQL Server 外的所有数据库要求 <code v-pre>upsert</code> 方法第二个参数中的列必须具有「主键」或「唯一」索引。此外，MySQL 数据库驱动程序会忽略 <code v-pre>upsert</code> 方法的第二个参数，并始终使用表的「主键」和「唯一」索引来检测现有记录。</p>
</blockquote>
<h2 id="删除模型" tabindex="-1"><a class="header-anchor" href="#删除模型"><span>删除模型</span></a></h2>
<p>想删除模型，你可以调用模型实例的 delete 方法:</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Models<span class="token punctuation">\</span>Flight</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$flight</span> <span class="token operator">=</span> <span class="token class-name static-context">Flight</span><span class="token operator">::</span><span class="token function">find</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$flight</span><span class="token operator">-></span><span class="token function">delete</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>你可以调用 <code v-pre>truncate</code> 方法来删除所有模型关联的数据库记录。 <code v-pre>truncate</code> 操作还将重置模型关联表上的所有自动递增 ID：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Flight</span><span class="token operator">::</span><span class="token function">truncate</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h4 id="通过其主键删除现有模型" tabindex="-1"><a class="header-anchor" href="#通过其主键删除现有模型"><span>通过其主键删除现有模型</span></a></h4>
<p>在上面的示例中，我们在调用 <code v-pre>delete</code> 方法之前从数据库中检索模型。但是，如果你知道模型的主键，则可以通过调用 <code v-pre>destroy</code> 方法删除模型而无需显式检索它。除了接受单个主键之外，<code v-pre>destroy</code> 方法还将接受多个主键、主键数组或主键 <a href="https://learnku.com/docs/laravel/11.x/collectionsmd" target="_blank" rel="noopener noreferrer">集合</a>：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Flight</span><span class="token operator">::</span><span class="token function">destroy</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token class-name static-context">Flight</span><span class="token operator">::</span><span class="token function">destroy</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token class-name static-context">Flight</span><span class="token operator">::</span><span class="token function">destroy</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token class-name static-context">Flight</span><span class="token operator">::</span><span class="token function">destroy</span><span class="token punctuation">(</span><span class="token function">collect</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><blockquote>
<p><strong>注意</strong><br>
<code v-pre>destroy</code> 方法单独加载每个模型并调用 <code v-pre>delete</code> 方法，以便为每个模型正确触发 <code v-pre>deleting</code> 和 <code v-pre>deleted</code> 事件。</p>
</blockquote>
<h4 id="使用查询删除模型" tabindex="-1"><a class="header-anchor" href="#使用查询删除模型"><span>使用查询删除模型</span></a></h4>
<p>当然，你可以构建一个 Eloquent 查询来删除所有符合你查询条件的模型。在此示例中，我们将删除所有标记为非活动的航班。与批量更新一样，批量删除不会为被删除的模型触发模型事件：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$deleted</span> <span class="token operator">=</span> <span class="token class-name static-context">Flight</span><span class="token operator">::</span><span class="token function">where</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'active'</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">delete</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><blockquote>
<p><strong>注意</strong><br>
通过 Eloquent 执行批量删除语句时，不会为被删除模型触发 <code v-pre>deleting</code> 和 <code v-pre>deleted</code> 模型事件。这是因为执行删除语句时，模型实际上从未被检索。</p>
</blockquote>
<h3 id="软删除" tabindex="-1"><a class="header-anchor" href="#软删除"><span>软删除</span></a></h3>
<p>除了从数据库中实际移除记录外，Eloquent 还可以对模型执行「软删除」。当模型被软删除时，它们实际上并没有从数据库中移除。相反，在模型上设置了 <code v-pre>deleted_at</code> 属性，标明模型被&quot;删除&quot;的日期和时间。要为模型启用软删除，请在模型中添加 <code v-pre>Illuminate\Database\Eloquent\SoftDeletes</code> trait：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">namespace</span> <span class="token package">App<span class="token punctuation">\</span>Models</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>Model</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>SoftDeletes</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">Flight</span> <span class="token keyword">extends</span> <span class="token class-name">Model</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">use</span> <span class="token package">SoftDeletes</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><blockquote>
<p><strong>注意</strong><br>
<code v-pre>SoftDeletes</code> trait 会自动将 <code v-pre>deleted_at</code> 属性转换成一个 <code v-pre>DateTime</code> / <code v-pre>Carbon</code> 实例。</p>
</blockquote>
<p>你应该还要在你的数据库表中添加 <code v-pre>deleted_at</code> 列。Laravel <a href="https://learnku.com/docs/laravel/11.x/migrationsmd" target="_blank" rel="noopener noreferrer">模式构建器</a> 包含一个助手方法来创建此列：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Schema<span class="token punctuation">\</span>Blueprint</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Support<span class="token punctuation">\</span>Facades<span class="token punctuation">\</span>Schema</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token class-name static-context">Schema</span><span class="token operator">::</span><span class="token function">table</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'flights'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token class-name type-declaration">Blueprint</span> <span class="token variable">$table</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token variable">$table</span><span class="token operator">-></span><span class="token function">softDeletes</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token class-name static-context">Schema</span><span class="token operator">::</span><span class="token function">table</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'flights'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token class-name type-declaration">Blueprint</span> <span class="token variable">$table</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token variable">$table</span><span class="token operator">-></span><span class="token function">dropSoftDeletes</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>现在，当你对模型调用 <code v-pre>delete</code> 方法时，<code v-pre>deleted_at</code> 列将设为当前日期和时间。然而，模型的数据库记录将保留在表中。查询使用软删除的模型时，软删除的模型将会自动从所有查询结果中排除。</p>
<p>要确定给定模型实例是否已被软删除，你可以使用 <code v-pre>trashed</code> 方法：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token variable">$flight</span><span class="token operator">-></span><span class="token function">trashed</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// ...</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="恢复软删除的模型" tabindex="-1"><a class="header-anchor" href="#恢复软删除的模型"><span>恢复软删除的模型</span></a></h4>
<p>有时你可能想要「撤销删除」一个软删除的模型。要恢复一个软删除的模型，你可以在模型实例上调用 <code v-pre>restore</code> 方法。<code v-pre>restore</code> 方法将模型的 <code v-pre>deleted_at</code> 列设置为 <code v-pre>null</code>：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$flight</span><span class="token operator">-></span><span class="token function">restore</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>你还可以在查询中使用 <code v-pre>restore</code> 方法来恢复多个模型。同样，像其他「批量」操作一样，这不会为被恢复的模型触发任何模型事件：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Flight</span><span class="token operator">::</span><span class="token function">withTrashed</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">        <span class="token operator">-></span><span class="token function">where</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'airline_id'</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span></span>
<span class="line">        <span class="token operator">-></span><span class="token function">restore</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code v-pre>restore</code> 方法也能用于构建<a href="https://learnku.com/docs/laravel/11.x/eloquent-relationshipsmd" target="_blank" rel="noopener noreferrer">关联查询</a>：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$flight</span><span class="token operator">-></span><span class="token function">history</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">restore</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h4 id="永久删除模型" tabindex="-1"><a class="header-anchor" href="#永久删除模型"><span>永久删除模型</span></a></h4>
<p>有时你可能需要从数据库中真正移除一个模型。你可以使用 <code v-pre>forceDelete</code> 方法从数据库表中永久删除一个软删除的模型：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$flight</span><span class="token operator">-></span><span class="token function">forceDelete</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>在构建 Eloquent 关系查询时也可以使用 <code v-pre>forceDelete</code> 方法：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$flight</span><span class="token operator">-></span><span class="token function">history</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">forceDelete</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h3 id="查询软删除的模型" tabindex="-1"><a class="header-anchor" href="#查询软删除的模型"><span>查询软删除的模型</span></a></h3>
<h4 id="包括软删除的模型" tabindex="-1"><a class="header-anchor" href="#包括软删除的模型"><span>包括软删除的模型</span></a></h4>
<p>如上所述，软删除的模型在查询结果中会自动排除。然而，你可以通过在查询上调用 <code v-pre>withTrashed</code> 方法来强制包含软删除的模型在查询结果中：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Models<span class="token punctuation">\</span>Flight</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$flights</span> <span class="token operator">=</span> <span class="token class-name static-context">Flight</span><span class="token operator">::</span><span class="token function">withTrashed</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">                <span class="token operator">-></span><span class="token function">where</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'account_id'</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span></span>
<span class="line">                <span class="token operator">-></span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>在构建<a href="https://learnku.com/docs/laravel/11.x/eloquent-relationshipsmd" target="_blank" rel="noopener noreferrer">关联查询</a> 时，也可以调用 <code v-pre>withTrashed</code> 方法：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$flight</span><span class="token operator">-></span><span class="token function">history</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">withTrashed</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h4 id="只检索软删除的模型" tabindex="-1"><a class="header-anchor" href="#只检索软删除的模型"><span>只检索软删除的模型</span></a></h4>
<p><code v-pre>onlyTrashed</code> 方法将检索<strong>只被</strong>软删除的模型：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$flights</span> <span class="token operator">=</span> <span class="token class-name static-context">Flight</span><span class="token operator">::</span><span class="token function">onlyTrashed</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">                <span class="token operator">-></span><span class="token function">where</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'airline_id'</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span></span>
<span class="line">                <span class="token operator">-></span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="修剪模型" tabindex="-1"><a class="header-anchor" href="#修剪模型"><span>修剪模型</span></a></h2>
<p>有时你可能需要定期删除不再需要的模型。为此，你可以为你希望定期清理的模型添加 <code v-pre>Illuminate\Database\Eloquent\Prunable</code> 或 <code v-pre>Illuminate\Database\Eloquent\MassPrunable</code> trait。在为模型添加了其中一个 trait 后，实现一个返回 Eloquent 查询构建器的 <code v-pre>prunable</code> 方法，用于解析不再需要的模型：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">namespace</span> <span class="token package">App<span class="token punctuation">\</span>Models</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>Builder</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>Model</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>Prunable</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">Flight</span> <span class="token keyword">extends</span> <span class="token class-name">Model</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">use</span> <span class="token package">Prunable</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * 获取可修剪模型查询构造器</span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">prunable</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token class-name return-type">Builder</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token keyword">return</span> <span class="token keyword static-context">static</span><span class="token operator">::</span><span class="token function">where</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'created_at'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'&lt;='</span><span class="token punctuation">,</span> <span class="token function">now</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">subMonth</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>当将模型标记为 <code v-pre>Prunable</code> 时，你还可以在模型上定义一个 <code v-pre>pruning</code> 方法。在删除模型之前，该方法将被调用。在模型从数据库中被永久移除之前，此方法可用于删除与模型相关联的任何其他资源，如存储的文件：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token doc-comment comment">/**</span>
<span class="line"> * 为修剪准备模型</span>
<span class="line"> */</span></span>
<span class="line"><span class="token keyword">protected</span> <span class="token keyword">function</span> <span class="token function-definition function">pruning</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">void</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// ...</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>配置可修剪模型后，你应该在应用程序的 <code v-pre>routes/console.php</code> 文件中安排 <code v-pre>model:prune</code> Artisan 命令。你可以自由选择合适的间隔运行此命令：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Support<span class="token punctuation">\</span>Facades<span class="token punctuation">\</span>Schedule</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token class-name static-context">Schedule</span><span class="token operator">::</span><span class="token function">command</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'model:prune'</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">daily</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>在幕后，<code v-pre>model:prune</code> 命令将自动侦测应用的 <code v-pre>app/Models</code> 目录中的「Prunable」模型。如果你的模型位置不同，你可以使用 <code v-pre>--model</code> 选项来指定模型类名：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Schedule</span><span class="token operator">::</span><span class="token function">command</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'model:prune'</span><span class="token punctuation">,</span> <span class="token punctuation">[</span></span>
<span class="line">    <span class="token string single-quoted-string">'--model'</span> <span class="token operator">=></span> <span class="token punctuation">[</span><span class="token class-name static-context">Address</span><span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">,</span> <span class="token class-name static-context">Flight</span><span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line"><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">daily</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>如果你希望在修剪所有其他检测到的模型时排除某些模型，你可以使用 <code v-pre>--except</code> 选项：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Schedule</span><span class="token operator">::</span><span class="token function">command</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'model:prune'</span><span class="token punctuation">,</span> <span class="token punctuation">[</span></span>
<span class="line">    <span class="token string single-quoted-string">'--except'</span> <span class="token operator">=></span> <span class="token punctuation">[</span><span class="token class-name static-context">Address</span><span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">,</span> <span class="token class-name static-context">Flight</span><span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line"><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">daily</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>你可以执行带有 <code v-pre>--pretend</code> 选项的 <code v-pre>model:prune</code> 命令来测试你的 <code v-pre>prunable</code> 查询。测试时，<code v-pre>model:prune</code> 命令将只报告如果命令实际运行，将修剪多少记录：</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh" data-title="sh"><pre v-pre class="language-bash"><code><span class="line">php artisan model:prune <span class="token parameter variable">--pretend</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><blockquote>
<p><strong>注意</strong><br>
如果软删除的模型符合可修剪查询，则将被永久删除（<code v-pre>forceDelete</code>）。</p>
</blockquote>
<h4 id="批量修剪模型" tabindex="-1"><a class="header-anchor" href="#批量修剪模型"><span>批量修剪模型</span></a></h4>
<p>当模型使用 <code v-pre>Illuminate\Database\Eloquent\MassPrunable</code> trait 标记时，模型将通过使用批量删除查询从数据库中删除。因此，不会调用 <code v-pre>pruning</code> 方法，也不会触发 <code v-pre>deleting</code> 和 <code v-pre>deleted</code> 模型事件。这是因为在删除前模型从未被检索，因此更高效：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">namespace</span> <span class="token package">App<span class="token punctuation">\</span>Models</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>Builder</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>Model</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>MassPrunable</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">Flight</span> <span class="token keyword">extends</span> <span class="token class-name">Model</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">use</span> <span class="token package">MassPrunable</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * 获取可修剪模型查询</span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">prunable</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token class-name return-type">Builder</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token keyword">return</span> <span class="token keyword static-context">static</span><span class="token operator">::</span><span class="token function">where</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'created_at'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'&lt;='</span><span class="token punctuation">,</span> <span class="token function">now</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">subMonth</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="复制模型" tabindex="-1"><a class="header-anchor" href="#复制模型"><span>复制模型</span></a></h2>
<p>你可以使用 <code v-pre>replicate</code> 方法创建一个现有模型实例的未保存副本。当你有很多共享许多相同属性的模型实例时，此方法特别有用：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Models<span class="token punctuation">\</span>Address</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$shipping</span> <span class="token operator">=</span> <span class="token class-name static-context">Address</span><span class="token operator">::</span><span class="token function">create</span><span class="token punctuation">(</span><span class="token punctuation">[</span></span>
<span class="line">    <span class="token string single-quoted-string">'type'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'shipping'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token string single-quoted-string">'line_1'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'123 Example Street'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token string single-quoted-string">'city'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'Victorville'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token string single-quoted-string">'state'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'CA'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token string single-quoted-string">'postcode'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'90001'</span><span class="token punctuation">,</span></span>
<span class="line"><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$billing</span> <span class="token operator">=</span> <span class="token variable">$shipping</span><span class="token operator">-></span><span class="token function">replicate</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">fill</span><span class="token punctuation">(</span><span class="token punctuation">[</span></span>
<span class="line">    <span class="token string single-quoted-string">'type'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'billing'</span></span>
<span class="line"><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$billing</span><span class="token operator">-></span><span class="token function">save</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>要排除一个或多个属性，不被复制到新模型，你可以传递一个数组给 <code v-pre>replicate</code> 方法：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$flight</span> <span class="token operator">=</span> <span class="token class-name static-context">Flight</span><span class="token operator">::</span><span class="token function">create</span><span class="token punctuation">(</span><span class="token punctuation">[</span></span>
<span class="line">    <span class="token string single-quoted-string">'destination'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'LAX'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token string single-quoted-string">'origin'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'LHR'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token string single-quoted-string">'last_flown'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'2020-03-04 11:00:00'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token string single-quoted-string">'last_pilot_id'</span> <span class="token operator">=></span> <span class="token number">747</span><span class="token punctuation">,</span></span>
<span class="line"><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$flight</span> <span class="token operator">=</span> <span class="token variable">$flight</span><span class="token operator">-></span><span class="token function">replicate</span><span class="token punctuation">(</span><span class="token punctuation">[</span></span>
<span class="line">    <span class="token string single-quoted-string">'last_flown'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token string single-quoted-string">'last_pilot_id'</span></span>
<span class="line"><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="查询作用域" tabindex="-1"><a class="header-anchor" href="#查询作用域"><span>查询作用域</span></a></h2>
<h3 id="全局作用域" tabindex="-1"><a class="header-anchor" href="#全局作用域"><span>全局作用域</span></a></h3>
<p>全局作用域允许你为给定模型的所有查询添加约束。Laravel 自己的<a href="#soft-deleting">软删除</a>功能使用全局作用域来只从数据库中检索「非删除」的模型。编写你自己的全局作用域可以提供一种方便的方式，确保给定模型的每个查询都接受某些约束。</p>
<h4 id="生成作用域" tabindex="-1"><a class="header-anchor" href="#生成作用域"><span>生成作用域</span></a></h4>
<p>要生成一个新的全局作用域，你可以调用 <code v-pre>make:scope</code> Artisan 命令，生成的作用域将放置在你的应用程序的 <code v-pre>app/Models/Scopes</code> 目录中：</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh" data-title="sh"><pre v-pre class="language-bash"><code><span class="line">php artisan make:scope AncientScope</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h4 id="编写全局作用域" tabindex="-1"><a class="header-anchor" href="#编写全局作用域"><span>编写全局作用域</span></a></h4>
<p>编写全局作用域很简单。首先，使用 <code v-pre>make:scope</code> 命令生成一个实现 <code v-pre>Illuminate\Database\Eloquent\Scope</code> 接口的类。<code v-pre>Scope</code> 接口要求你实现一个方法：<code v-pre>apply</code>。<code v-pre>apply</code> 方法可以根据需要向查询添加 <code v-pre>where</code> 约束或其他类型的子句：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">namespace</span> <span class="token package">App<span class="token punctuation">\</span>Models<span class="token punctuation">\</span>Scopes</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>Builder</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>Model</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>Scope</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">AncientScope</span> <span class="token keyword">implements</span> <span class="token class-name">Scope</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * 将作用域应用到给定的 Eloquent 查询构建器</span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">apply</span><span class="token punctuation">(</span><span class="token class-name type-declaration">Builder</span> <span class="token variable">$builder</span><span class="token punctuation">,</span> <span class="token class-name type-declaration">Model</span> <span class="token variable">$model</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">void</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token variable">$builder</span><span class="token operator">-></span><span class="token function">where</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'created_at'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'&lt;'</span><span class="token punctuation">,</span> <span class="token function">now</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">subYears</span><span class="token punctuation">(</span><span class="token number">2000</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><blockquote>
<p><strong>注意</strong><br>
如果你的全局作用域正在向查询的 select 子句中添加列，你应该使用 <code v-pre>addSelect</code> 方法而不是 <code v-pre>select</code>。这样可以防止无意中替换查询现有的 select 子句。</p>
</blockquote>
<h4 id="应用全局作用域" tabindex="-1"><a class="header-anchor" href="#应用全局作用域"><span>应用全局作用域</span></a></h4>
<p>要给模型分配一个全局作用域，可以简单地在模型上使用 <code v-pre>ScopedBy</code> 属性：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">namespace</span> <span class="token package">App<span class="token punctuation">\</span>Models</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Models<span class="token punctuation">\</span>Scopes<span class="token punctuation">\</span>AncientScope</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>Attributes<span class="token punctuation">\</span>ScopedBy</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token attribute"><span class="token delimiter punctuation">#[</span><span class="token attribute-content"><span class="token attribute-class-name class-name">ScopedBy</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token attribute-class-name class-name">AncientScope</span><span class="token operator">::</span><span class="token constant">class</span><span class="token punctuation">]</span><span class="token punctuation">)</span></span><span class="token delimiter punctuation">]</span></span></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">User</span> <span class="token keyword">extends</span> <span class="token class-name">Model</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">//</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>或者，你可以通过覆盖模型的 <code v-pre>booted</code> 方法并调用模型的 <code v-pre>addGlobalScope</code> 方法来手动注册全局作用域。<code v-pre>addGlobalScope</code> 方法接受作用域实例作为唯一参数：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">namespace</span> <span class="token package">App<span class="token punctuation">\</span>Models</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Models<span class="token punctuation">\</span>Scopes<span class="token punctuation">\</span>AncientScope</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>Model</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">User</span> <span class="token keyword">extends</span> <span class="token class-name">Model</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     *  模型的「booted」方法</span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">protected</span> <span class="token keyword">static</span> <span class="token keyword">function</span> <span class="token function-definition function">booted</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">void</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token keyword static-context">static</span><span class="token operator">::</span><span class="token function">addGlobalScope</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">AncientScope</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>在上面的例子中，给 <code v-pre>App\Models\User</code> 模型添加了作用域之后，调用 <code v-pre>User::all()</code> 方法将执行以下 SQL 查询：</p>
<div class="language-sql line-numbers-mode" data-highlighter="prismjs" data-ext="sql" data-title="sql"><pre v-pre class="language-sql"><code><span class="line"><span class="token keyword">select</span> <span class="token operator">*</span> <span class="token keyword">from</span> <span class="token identifier"><span class="token punctuation">`</span>users<span class="token punctuation">`</span></span> <span class="token keyword">where</span> <span class="token identifier"><span class="token punctuation">`</span>created_at<span class="token punctuation">`</span></span> <span class="token operator">&lt;</span> <span class="token number">0021</span><span class="token operator">-</span><span class="token number">02</span><span class="token operator">-</span><span class="token number">18</span> <span class="token number">00</span>:<span class="token number">00</span>:<span class="token number">00</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h4 id="匿名全局作用域" tabindex="-1"><a class="header-anchor" href="#匿名全局作用域"><span>匿名全局作用域</span></a></h4>
<p>Eloquent 也允许你使用闭包定义全局作用域，这对于不需要单独类的简单作用域来说特别有用。当使用闭包定义全局作用域时，应该在 <code v-pre>addGlobalScope</code> 方法的第一个参数传递一个你自己选择的作用域名称：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">namespace</span> <span class="token package">App<span class="token punctuation">\</span>Models</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>Builder</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>Model</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">User</span> <span class="token keyword">extends</span> <span class="token class-name">Model</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * 模型的「booted」方法</span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">protected</span> <span class="token keyword">static</span> <span class="token keyword">function</span> <span class="token function-definition function">booted</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">void</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token keyword static-context">static</span><span class="token operator">::</span><span class="token function">addGlobalScope</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'ancient'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token class-name type-declaration">Builder</span> <span class="token variable">$builder</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">            <span class="token variable">$builder</span><span class="token operator">-></span><span class="token function">where</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'created_at'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'&lt;'</span><span class="token punctuation">,</span> <span class="token function">now</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">subYears</span><span class="token punctuation">(</span><span class="token number">2000</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">        <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="移除全局作用域" tabindex="-1"><a class="header-anchor" href="#移除全局作用域"><span>移除全局作用域</span></a></h4>
<p>如果你想为给定查询移除一个全局作用域，可以使用 <code v-pre>withoutGlobalScope</code> 方法。此方法接受全局作用域的类名称作为唯一参数：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">User</span><span class="token operator">::</span><span class="token function">withoutGlobalScope</span><span class="token punctuation">(</span><span class="token class-name static-context">AncientScope</span><span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>或者，如果你是使用闭包定义的全局作用域，应该传递你指定给全局作用域的字符串名称：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">User</span><span class="token operator">::</span><span class="token function">withoutGlobalScope</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'ancient'</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>如果你想移除查询的一个或多个甚至所有全局作用域，可以使用 <code v-pre>withoutGlobalScopes</code> 方法：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token comment">// 移除所有全局作用域...</span></span>
<span class="line"><span class="token class-name static-context">User</span><span class="token operator">::</span><span class="token function">withoutGlobalScopes</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token comment">// 移除一些全局作用域...</span></span>
<span class="line"><span class="token class-name static-context">User</span><span class="token operator">::</span><span class="token function">withoutGlobalScopes</span><span class="token punctuation">(</span><span class="token punctuation">[</span></span>
<span class="line">    <span class="token class-name static-context">FirstScope</span><span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">,</span> <span class="token class-name static-context">SecondScope</span><span class="token operator">::</span><span class="token keyword">class</span></span>
<span class="line"><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="局部作用域" tabindex="-1"><a class="header-anchor" href="#局部作用域"><span>局部作用域</span></a></h3>
<p>局部作用域允许你定义可在应用中简单重用的常见查询约束集合。例如，你可能经常需要检索所有被认为是 「流行」的用户。要定义作用域，请在 Eloquent 模型方法前添加 <code v-pre>scope</code> 前缀。</p>
<p>作用域总是返回一个查询构造器实例或者 <code v-pre>void</code>：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">namespace</span> <span class="token package">App<span class="token punctuation">\</span>Models</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>Builder</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>Model</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">User</span> <span class="token keyword">extends</span> <span class="token class-name">Model</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * 只查询受欢迎的用户的作用域</span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">scopePopular</span><span class="token punctuation">(</span><span class="token class-name type-declaration">Builder</span> <span class="token variable">$query</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">void</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token variable">$query</span><span class="token operator">-></span><span class="token function">where</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'votes'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'>'</span><span class="token punctuation">,</span> <span class="token number">100</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * 只查询 active 用户的作用域</span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">scopeActive</span><span class="token punctuation">(</span><span class="token class-name type-declaration">Builder</span> <span class="token variable">$query</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">void</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token variable">$query</span><span class="token operator">-></span><span class="token function">where</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'active'</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="使用局部作用域" tabindex="-1"><a class="header-anchor" href="#使用局部作用域"><span>使用局部作用域</span></a></h4>
<p>一旦定义了作用域，就可以在查询该模型时调用作用域方法。不过，在调用这些方法时不必包含 <code v-pre>scope</code> 前缀。甚至可以链式调用多个作用域，例如：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Models<span class="token punctuation">\</span>User</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$users</span> <span class="token operator">=</span> <span class="token class-name static-context">User</span><span class="token operator">::</span><span class="token function">popular</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">active</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">orderBy</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'created_at'</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>通过 <code v-pre>or</code> 查询运算符结合多个 Eloquent 模型作用域可能需要使用闭包来实现正确的<a href="https://learnku.com/docs/laravel/11.x/queriesmd#logical-grouping" target="_blank" rel="noopener noreferrer">逻辑分组</a>：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$users</span> <span class="token operator">=</span> <span class="token class-name static-context">User</span><span class="token operator">::</span><span class="token function">popular</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">orWhere</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token class-name type-declaration">Builder</span> <span class="token variable">$query</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token variable">$query</span><span class="token operator">-></span><span class="token function">active</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>然而，由于这可能很麻烦，Laravel 提供了「高阶」 <code v-pre>orWhere</code> 方法，允许你流畅地将作用域链在一起，无需使用闭包：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$users</span> <span class="token operator">=</span> <span class="token class-name static-context">User</span><span class="token operator">::</span><span class="token function">popular</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token property">orWhere</span><span class="token operator">-></span><span class="token function">active</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h4 id="动态作用域" tabindex="-1"><a class="header-anchor" href="#动态作用域"><span>动态作用域</span></a></h4>
<p>有时你可能希望定义一个接受参数的作用域。首先，只需向你的作用域方法签名中添加额外的参数。作用域参数应在 <code v-pre>$query</code> 参数之后定义：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">namespace</span> <span class="token package">App<span class="token punctuation">\</span>Models</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>Builder</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>Model</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">User</span> <span class="token keyword">extends</span> <span class="token class-name">Model</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     *  作用域限制为仅包含给定类型的用户</span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">scopeOfType</span><span class="token punctuation">(</span><span class="token class-name type-declaration">Builder</span> <span class="token variable">$query</span><span class="token punctuation">,</span> <span class="token keyword type-hint">string</span> <span class="token variable">$type</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">void</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token variable">$query</span><span class="token operator">-></span><span class="token function">where</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'type'</span><span class="token punctuation">,</span> <span class="token variable">$type</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>添加了预期参数到作用域方法签名后，你可以在调用作用域时传递参数：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$users</span> <span class="token operator">=</span> <span class="token class-name static-context">User</span><span class="token operator">::</span><span class="token function">ofType</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'admin'</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h2 id="模型对比" tabindex="-1"><a class="header-anchor" href="#模型对比"><span>模型对比</span></a></h2>
<p>有时你可能需要确定两个模型是否是「相同&quot;」的。<code v-pre>is</code> 和 <code v-pre>isNot</code> 方法可用于快速验证两个模型是否具有相同的主键、表和数据库连接：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token variable">$post</span><span class="token operator">-></span><span class="token function">is</span><span class="token punctuation">(</span><span class="token variable">$anotherPost</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// ...</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token variable">$post</span><span class="token operator">-></span><span class="token function">isNot</span><span class="token punctuation">(</span><span class="token variable">$anotherPost</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// ...</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>当你使用 <code v-pre>belongsTo</code>, <code v-pre>hasOne</code>, <code v-pre>morphTo</code>, 和 <code v-pre>morphOne</code> <a href="https://learnku.com/docs/laravel/11.x/eloquent-relationshipsmd" target="_blank" rel="noopener noreferrer">关联</a>时，<code v-pre>is</code> 和 <code v-pre>isNot</code> 方法也可以使用。当你想要比较相关模型而不发出查询来检索模型时，这个方法特别有用：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token variable">$post</span><span class="token operator">-></span><span class="token function">author</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">is</span><span class="token punctuation">(</span><span class="token variable">$user</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// ...</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="事件" tabindex="-1"><a class="header-anchor" href="#事件"><span>事件</span></a></h2>
<blockquote>
<p><strong>注意</strong><br>
想直接将 Eloquent 事件广播到你的客户端应用？查看 Laravel 的 <a href="https://learnku.com/docs/laravel/11.x/broadcastingmd#model-broadcasting" target="_blank" rel="noopener noreferrer">模型事件广播</a>。</p>
</blockquote>
<p>Eloquent 模型触发了几个事件，允许你挂接到模型生命周期的以下时刻：<code v-pre>retrieved</code>, <code v-pre>creating</code>, <code v-pre>created</code>, <code v-pre>updating</code>, <code v-pre>updated</code>, <code v-pre>saving</code>, <code v-pre>saved</code>, <code v-pre>deleting</code>, <code v-pre>deleted</code>, <code v-pre>trashed</code>, <code v-pre>forceDeleting</code>, <code v-pre>forceDeleted</code>, <code v-pre>restoring</code>, <code v-pre>restored</code>, 和 <code v-pre>replicating</code>。</p>
<p>当从数据库检索现有的模型时，会触发 <code v-pre>retrieved</code> 事件。当第一次保存新模型时，将触发 <code v-pre>creating</code> 和 <code v-pre>created</code> 事件。当现有模型被修改并且调用 <code v-pre>save</code> 方法时，将会触发 <code v-pre>updating</code> / <code v-pre>updated</code> 事件。当创建或更新模型时，即使模型的属性没有被更改，也会触发 <code v-pre>saving</code> / <code v-pre>saved</code> 事件。以 <code v-pre>-ing</code> 结尾的事件名称在对模型所做的更改被持久化之前被调度，而以 <code v-pre>-ed</code> 结尾的事件在更改被持久化到模型之后触发。</p>
<p>要开始监听模型事件，请在你的 Eloquent 模型上定义一个 <code v-pre>$dispatchesEvents</code> 属性。这个属性将 Eloquent 模型的生命周期的各个点映射到你自己的<a href="https://learnku.com/docs/laravel/11.x/eventsmd" target="_blank" rel="noopener noreferrer">事件类</a>。每个模型事件类都应该期望通过其构造函数接收受影响模型的实例：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">namespace</span> <span class="token package">App<span class="token punctuation">\</span>Models</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Events<span class="token punctuation">\</span>UserDeleted</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Events<span class="token punctuation">\</span>UserSaved</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Foundation<span class="token punctuation">\</span>Auth<span class="token punctuation">\</span>User</span> <span class="token keyword">as</span> Authenticatable<span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Notifications<span class="token punctuation">\</span>Notifiable</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">User</span> <span class="token keyword">extends</span> <span class="token class-name">Authenticatable</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">use</span> <span class="token package">Notifiable</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * 模型的事件映射</span>
<span class="line">     *</span>
<span class="line">     * <span class="token keyword">@var</span> <span class="token class-name"><span class="token keyword">array</span></span>&lt;string, string></span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">protected</span> <span class="token variable">$dispatchesEvents</span> <span class="token operator">=</span> <span class="token punctuation">[</span></span>
<span class="line">        <span class="token string single-quoted-string">'saved'</span> <span class="token operator">=></span> <span class="token class-name static-context">UserSaved</span><span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token string single-quoted-string">'deleted'</span> <span class="token operator">=></span> <span class="token class-name static-context">UserDeleted</span><span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>在定义并映射你的 Eloquent 事件后，你可以使用<a href="https://learnku.com/docs/laravel/11.x/events#defining-listenersmd" target="_blank" rel="noopener noreferrer">事件监听器</a>来处理事件。</p>
<blockquote>
<p><strong>注意</strong><br>
当通过 Eloquent 发起批量更新或删除查询时，不会为受影响的模型调度 <code v-pre>saved</code>，<code v-pre>updated</code>，<code v-pre>deleting</code> 和 <code v-pre>deleted</code> 模型事件。这是因为在执行批量更新或删除时，模型根本不会被检索。</p>
</blockquote>
<h3 id="使用闭包" tabindex="-1"><a class="header-anchor" href="#使用闭包"><span>使用闭包</span></a></h3>
<p>如果需要在多个模型事件被触发时执行操作，可以注册闭包。通常，这些闭包应该在模型的 <code v-pre>booted</code> 方法中注册：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">namespace</span> <span class="token package">App<span class="token punctuation">\</span>Models</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>Model</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">User</span> <span class="token keyword">extends</span> <span class="token class-name">Model</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     *  模型的「booted」方法。</span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">protected</span> <span class="token keyword">static</span> <span class="token keyword">function</span> <span class="token function-definition function">booted</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">void</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token keyword static-context">static</span><span class="token operator">::</span><span class="token function">created</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token class-name type-declaration">User</span> <span class="token variable">$user</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">            <span class="token comment">// ...</span></span>
<span class="line">        <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>如有需要，当注册模型事件时，可以使用 <a href="https://learnku.com/docs/laravel/11.x/eventsmd#queuable-anonymous-event-listeners" target="_blank" rel="noopener noreferrer">队列匿名事件监听器</a>。这会指示 Laravel 使用应用程序的 <a href="https://learnku.com/docs/laravel/11.x/queuesmd" target="_blank" rel="noopener noreferrer">队列</a>在后台执行模型事件监听器：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token keyword">function</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Events<span class="token punctuation">\</span>queueable</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword static-context">static</span><span class="token operator">::</span><span class="token function">created</span><span class="token punctuation">(</span><span class="token function">queueable</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token class-name type-declaration">User</span> <span class="token variable">$user</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// ...</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="观察者" tabindex="-1"><a class="header-anchor" href="#观察者"><span>观察者</span></a></h3>
<h4 id="定义观察者" tabindex="-1"><a class="header-anchor" href="#定义观察者"><span>定义观察者</span></a></h4>
<p>如果监听给定模型的许多事件，可以使用观察者将所有监听器分组到一个类中。观察者类的方法名反映了你想要监听的 Eloquent 事件。这些方法中的每一个都将受影响的模型作为唯一参数。<code v-pre>make:observer</code> Artisan 命令是创建新的观察者类最简单的方式：</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh" data-title="sh"><pre v-pre class="language-bash"><code><span class="line">php artisan make:observer UserObserver <span class="token parameter variable">--model</span><span class="token operator">=</span>User</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>该命令会将新的观察者放在 <code v-pre>app/Observers</code> 目录中。如果此目录不存在，Artisan 会为你创建它。你的新观察者看起来如下：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">namespace</span> <span class="token package">App<span class="token punctuation">\</span>Observers</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Models<span class="token punctuation">\</span>User</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">UserObserver</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * 处理用户「created」事件</span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">created</span><span class="token punctuation">(</span><span class="token class-name type-declaration">User</span> <span class="token variable">$user</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">void</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token comment">// ...</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * 处理用户「updated」事件</span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">updated</span><span class="token punctuation">(</span><span class="token class-name type-declaration">User</span> <span class="token variable">$user</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">void</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token comment">// ...</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * 处理用户「deleted」事件</span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">deleted</span><span class="token punctuation">(</span><span class="token class-name type-declaration">User</span> <span class="token variable">$user</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">void</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token comment">// ...</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * 处理用户「restored」事件</span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">restored</span><span class="token punctuation">(</span><span class="token class-name type-declaration">User</span> <span class="token variable">$user</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">void</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token comment">// ...</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * 处理用户「forceDeleted」事件</span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">forceDeleted</span><span class="token punctuation">(</span><span class="token class-name type-declaration">User</span> <span class="token variable">$user</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">void</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token comment">// ...</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>要注册观察者，可以将 <code v-pre>ObservedBy</code> 属性放在相应的模型上：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Observers<span class="token punctuation">\</span>UserObserver</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>Attributes<span class="token punctuation">\</span>ObservedBy</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token attribute"><span class="token delimiter punctuation">#[</span><span class="token attribute-content"><span class="token attribute-class-name class-name">ObservedBy</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token attribute-class-name class-name">UserObserver</span><span class="token operator">::</span><span class="token constant">class</span><span class="token punctuation">]</span><span class="token punctuation">)</span></span><span class="token delimiter punctuation">]</span></span></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">User</span> <span class="token keyword">extends</span> <span class="token class-name">Authenticatable</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">//</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>或者，也可以通过在模型上调用 <code v-pre>observe</code> 方法来手动注册一个观察者。你可以在应用程序的 <code v-pre>AppServiceProvider</code> 类的 <code v-pre>boot</code> 方法中注册观察者：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Models<span class="token punctuation">\</span>User</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Observers<span class="token punctuation">\</span>UserObserver</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token doc-comment comment">/**</span>
<span class="line"> * 启动任何应用程序服务</span>
<span class="line"> */</span></span>
<span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">boot</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">void</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token class-name static-context">User</span><span class="token operator">::</span><span class="token function">observe</span><span class="token punctuation">(</span><span class="token class-name static-context">UserObserver</span><span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><blockquote>
<p><strong>技巧</strong><br>
观察者可以监听其他事件，例如「saving」和「retrieved」。这些事件在 <a href="#events">events</a> 文档中进行了描述。</p>
</blockquote>
<h4 id="观察者与数据库事务" tabindex="-1"><a class="header-anchor" href="#观察者与数据库事务"><span>观察者与数据库事务</span></a></h4>
<p>当模型在数据库事务中创建时，你可能希望指示观察者仅在数据库事务提交后执行其事件处理程序。你可以通过在观察者上实现 <code v-pre>ShouldHandleEventsAfterCommit</code> 接口来实现这一点。如果没有正在进行的数据库事务，事件处理程序将立即执行：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">namespace</span> <span class="token package">App<span class="token punctuation">\</span>Observers</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Models<span class="token punctuation">\</span>User</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Contracts<span class="token punctuation">\</span>Events<span class="token punctuation">\</span>ShouldHandleEventsAfterCommit</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">UserObserver</span> <span class="token keyword">implements</span> <span class="token class-name">ShouldHandleEventsAfterCommit</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * 处理用户「created」事件</span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">created</span><span class="token punctuation">(</span><span class="token class-name type-declaration">User</span> <span class="token variable">$user</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">void</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token comment">// ...</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="静默事件" tabindex="-1"><a class="header-anchor" href="#静默事件"><span>静默事件</span></a></h3>
<p>你可能偶尔需要临时「静默」模型触发的所有事件。你可以使用 <code v-pre>withoutEvents</code> 方法来实现。<code v-pre>withoutEvents</code> 方法接受一个闭包作为唯一参数。在此闭包内执行的任何代码都不会触发模型事件，闭包返回的任何值将由 <code v-pre>withoutEvents</code> 方法返回：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Models<span class="token punctuation">\</span>User</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$user</span> <span class="token operator">=</span> <span class="token class-name static-context">User</span><span class="token operator">::</span><span class="token function">withoutEvents</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token class-name static-context">User</span><span class="token operator">::</span><span class="token function">findOrFail</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">delete</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token keyword">return</span> <span class="token class-name static-context">User</span><span class="token operator">::</span><span class="token function">find</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="静默的保存单个模型" tabindex="-1"><a class="header-anchor" href="#静默的保存单个模型"><span>静默的保存单个模型</span></a></h4>
<p>有时你可能希望「保存」特定模型而不触发任何事件。你可以使用 <code v-pre>saveQuietly</code> 方法来完成这项操作：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$user</span> <span class="token operator">=</span> <span class="token class-name static-context">User</span><span class="token operator">::</span><span class="token function">findOrFail</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$user</span><span class="token operator">-></span><span class="token property">name</span> <span class="token operator">=</span> <span class="token string single-quoted-string">'Victoria Faith'</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$user</span><span class="token operator">-></span><span class="token function">saveQuietly</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>你也可以不触发任何事件地进行「更新」、「删除」、「软删除」、「恢复」和「复制」特定模型：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$user</span><span class="token operator">-></span><span class="token function">deleteQuietly</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token variable">$user</span><span class="token operator">-></span><span class="token function">forceDeleteQuietly</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token variable">$user</span><span class="token operator">-></span><span class="token function">restoreQuietly</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><blockquote>
<p>本译文仅用于学习和交流目的，转载请务必注明文章译者、出处、和本文链接<br>
我们的翻译工作遵照 <a href="https://learnku.com/docs/guide/cc4.0/6589" target="_blank" rel="noopener noreferrer">CC 协议</a>，如果我们的工作有侵犯到您的权益，请及时联系我们。</p>
</blockquote>
<hr>
<blockquote>
<p>原文地址：<a href="https://learnku.com/docs/laravel/11.x/eloquentmd/16702" target="_blank" rel="noopener noreferrer">https://learnku.com/docs/laravel/11.x/el...</a></p>
<p>译文地址：<a href="https://learnku.com/docs/laravel/11.x/eloquentmd/16702" target="_blank" rel="noopener noreferrer">https://learnku.com/docs/laravel/11.x/el...</a></p>
</blockquote>
</div></template>


